How to compare two JSON objects with the same elements in Python

Asked

Viewed 516 times

2

I have two Apis that bring me the data in JSON. I’m just not able to make the logic to compare the two.

API 1:

inserir a descrição da imagem aqui

API 2:

inserir a descrição da imagem aqui

My logic is to compare the two on the die FlightID and if it’s the same, give me the result.

import requests
import json

def flights():
    url = requests.get('http://infinite-flight-public-api.cloudapp.net/v1/Flights.aspx?'
                       'apikey=78879b1d-3ba3-47de-8e50-162f35dc6e04&sessionid=7e5dcd44-1fb5-49cc-bc2c-a9aab1f6a856')
    respo = json.loads(url.text)
    return respo



def flightPlans():
    url = requests.get('http://infinite-flight-public-api.cloudapp.net/v1/GetFlightPlans.aspx?'
                       'apikey=78879b1d-3ba3-47de-8e50-162f35dc6e04&sessionid=7e5dcd44-1fb5-49cc-bc2c-a9aab1f6a856')
    respo = json.loads(url.text)
    return respo



x = flights()
y = flightPlans()

for i in x:
    if "IFAB" in x[i]['DiplayName']:
        if x[i]['FlightID'] == y[i]['FlightID']:
            print(y[i]['Waypoints'])

You’re making a mistake.

PS C:\Users\Positivo\Desktop\api> & C:/Users/Positivo/AppData/Local/Programs/Python/Python37/python.exe c:/Users/Positivo/Desktop/api/models.py
Traceback (most recent call last):
  File "c:/Users/Positivo/Desktop/api/models.py", line 24, in <module>
    if "IFAB" in x[i]['DiplayName']:
TypeError: list indices must be integers or slices, not dict
PS C:\Users\Positivo\Desktop\api>

3 answers

4


If you print the return of the API’s, ie if you put a print(url.text) within the functions flights and flightPlans, will see that their return are JSON arrays:

[{'AircraftID': 'f11ed126-bce8 etc...
[{'AlternateDestinations': etc...

Notice that they start with [, which indicates that it is a JSON array, that the module json maps to Python lists. That is to say, x and y are lists.

And each element of the list is a dictionary containing the data of a flight. For example, taking the first elements of x (removing some data, to be shorter and clear):

[{'AircraftID': 'f11ed126-bce8-46ef-9265-69191c354575', ... 'VerticalSpeed': 3.269327180532855e-06},
{'AircraftID': '230ec095-5e36-4637-ba2f-68831b31e891', ... 'VerticalSpeed': 30.30824089050293},
{'AircraftID': 'bec63a00-a483-4427-a076-0f76dba0ee97', ... 'VerticalSpeed': 16.32938575744629},
... ]

Each element in the list is a dictionary (delimited by {}), and the elements are separated by commas.

So when you do for i in x, at each iteration the variable i contains one of the list elements, that is, one of the dictionaries. This means that you do not need to do x[i]['DisplayName'], just do i['DisplayName'], for i is already a dictionary.

In addition, for each element of x, you should check if he’s on y, and for that you need to go through the y every time, since there does not seem to be a guarantee of order of the returned data, then nothing guarantees that a FlighID of x is in the same position in y: the first FlighID of x may be at any position on the list y - not necessarily in the first - so you have to go through the whole list y for each element of x:

for flight in x:
    for plan in y:
        if flight['FlightID'] == plan['FlightID']:
            print(plan['Waypoints'])

Accessing now, I found several cases (follow the first ones, just to illustrate how the return would look):

['WPT', 'CELAK', 'BUGNE', 'CUSBU', 'KSEA']
['WPT', 'SYDNM', 'SYDSM', 'YSSY', 'MA34L', 'ATRET', 'DEENA', 'D178N', 'TAMMI', 'NOLEM', 'NFTF', 'NIUE', 'D064W', 'MMJC', 'D248H', 'PLAZA', 'MEBIP', 'MMMX']
['WPT', 'LAMBY', 'MCCAL', 'XS99', 'HUDZY', 'ZAPPO', 'GRIEG', 'KERNS', 'SOROY', 'KIAH']

Not directly related, but the functions that get the data from x and y are practically the same (only changes the URL), so would simplify a little, creating only a function to get the data of any URL.

And also worth give more meaningful names for the variables x and y (may seem like a silly detail, but better names help when programming):

def get_json(url):
    return json.loads(requests.get(url).text)

flights = get_json('http://infinite-flight-public-api.cloudapp.net/v1/Flights.aspx?'
                   'apikey=78879b1d-3ba3-47de-8e50-162f35dc6e04&sessionid=7e5dcd44-1fb5-49cc-bc2c-a9aab1f6a856')
plans = get_json('http://infinite-flight-public-api.cloudapp.net/v1/GetFlightPlans.aspx?'
                 'apikey=78879b1d-3ba3-47de-8e50-162f35dc6e04&sessionid=7e5dcd44-1fb5-49cc-bc2c-a9aab1f6a856')

for flight in flights:
    for plan in plans:
        if flight['FlightID'] == plan['FlightID']:
            print(plan['Waypoints'])
  • 1

    Good! I didn’t think about the detail of the elements' orders.

2

If I understand correctly, the first thing you should do is make sure that the two return the same number of elements and that you have the keys that you want to compare, in a test using your own functions, I could see that the two do not have the same number of items and each call returns different number, example of one of the calls:

x = flights()
y = flightPlans()
print('Len de x:', len(x))
print('Len de y:', len(y))

Len de x: 403
Len de y: 5798

Therefore Voce would have to make the comparison from the one that returns the smallest number of elements (remembering that the return is a list of objects of type Dict), going through all the dictionaries of the list of the smallest number of elements and making the comparison with the element of the same index in the other list, for this we will determine which list is smaller:

 # Se for igual, melhor e tanto faz    
_len = len(x) if len(x)<len(y) else len(y)

Now let’s make the comparisons:

for i in range(_len):
    if x[i]['FlightID']==y[i]['FlightID']:
        print(y[i]['Waypoints'])

In my tests were not found equal values.

Explaining the error of the code presented in the question:
When Voce does for i in x every iteration you get a dictionary from within the list x which will be assigned to i, so when Voce tries to do x[i]['FlightID'] == y[i]['FlightID'] an exception is raised with the error message:

TypeError: list indices must be integers or slices, not dict

That is, it is only possible to make reference to an element of a list atavés of an Indice that is an integer or 'slices' and not a dictionary.

Final remark:
If Voce prints any element of the Flightid key, you will notice that the value returned is what the name suggests an ID and UUID type, for example print(x[0]['FlightID']) returns: abc22393-cea3-4695-8ff1-0deb60f2eb80 then it seems unlikely that Voce will find identity values.

-1

Try trading your loop for

for i in range(len(x)):
    if "IFAB" in x[i]['DiplayName']:
        if x[i]['FlightID'] == y[i]['FlightID']:
            print(y[i]['Waypoints'])

Because in the format where this variable i loop for is not an index number to get the array item.

In this format above you can loop the list of objects and capture one by one and access their property.

  • If len(x) is greater than len(y) (what is possible) go bugar. :-)

  • @Well-aimed Sidon really this validation is necessary before performing the loop as measured _len = len(x) if len(x)<len(y) else len(y)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.