1
\$\begingroup\$

I have 4-deep JSON data structure. Basically its a list of dictionaries nested in a list of dictionaries. This is my first time working with this kind of nested data. Below I have done my best to reproduce the structure:

   data = [
    0 : {"name": "hotel1",
         "overall_rating": 4, 
         "reviews": [{"rating": 5, "review" : "best place ever"},
                     {"rating": 1, "review" : "toilet was blocked"}],
        }

    1 : {"name": "hotel2",
         "overall_rating": 4,
         "reviews": [{"rating":4, "review" : "welly nice"},
                      {"rating":3, "review" : "I couldn't bring my dog"}],
        }
    ]

What i want to do is write a function that can iterate over all the nested dictionaries and retrieve "rating" and "review". I have written the following program:

reviews = []
ratings = []

for index in range(len(data)):
    for key in data[index]:
        for key in range(len(data[index]['reviews'])):
            reviews.append(data[index]['reviews'][key]['review'])
            ratings.append(data[index]['reviews'][key]['rating'])

However, this loop only retrieves the ratings and reviews of the first nested. Additionally, it does this len(data) x len(dict) x len(reviews) times. Besides getting help with the loop I it would also be nice with some pointers to libraries that make dealing with this kind of data structure easier (if such a library exists).

\$\endgroup\$
  • \$\begingroup\$ So, is the code working? \$\endgroup\$ – TigerTV.ru Mar 9 '18 at 21:12
  • \$\begingroup\$ No, its not. But the question has been solved, \$\endgroup\$ – Daniel Hansen Mar 9 '18 at 21:43
  • \$\begingroup\$ To fix not working code use stackoverflow.com. codereview.stackexchange.com/help/dont-ask \$\endgroup\$ – TigerTV.ru Mar 9 '18 at 21:46
  • \$\begingroup\$ Thanks for the heads up! After following your link I realise that this question is indeed of-topic for codereview. Is there any way of migrating the question to stackoverflow.com? \$\endgroup\$ – Daniel Hansen Mar 9 '18 at 21:56
  • \$\begingroup\$ I don't know, maybe moderators will do this. \$\endgroup\$ – TigerTV.ru Mar 9 '18 at 22:24
2
\$\begingroup\$

Your data is slightly wrong - you're using list [] but then putting in keys (0, 1) - I'm going to assume it's a dict of dicts in my examples. However it wouldn't be that different if it was a list of dicts.

data = {
  0: {"name": "hotel1",
         "overall_rating": 4, 
         "reviews": [{"rating": 5, "review" : "best place ever"},
                     {"rating": 1, "review" : "toilet was blocked"}],
        },
  1:  {"name": "hotel2",
         "overall_rating": 4,
         "reviews": [{"rating":4, "review" : "welly nice"},
                      {"rating":3, "review" : "I couldn't bring my dog"}],
        }
    }

Your code makes one of the common mistakes that people new to python make, which is to not realise that you can iterate directly over things like lists and dictionaries - rather than having to get the length and then ask for the index of each item.

You can dramatically simplify your code by just iterating over the values in data directly, and then getting the reviews key of each 'child' dict:

ratings = []
reviews = []
for hotel in data.values():
    for review in hotel['reviews']:
        reviews.append(review['review'])
        ratings.append(review['rating'])

Note that this isn't really what most people would think of as processing a nested dict - since although the data is nested, it is all one level deep - so you can just ask for it at that level.

More complex examples are where you want the same data from multiply nested dictionaries, and have to resort to recursion to get it, e.g. getting all 'name' fields from the following family tree:

tree = {
  'name': 'Alice',
  'relation': 'grandmother',
  'child': {
    'name': 'Bob',
    'relation': 'father',
    'child': {
      'name': 'Charlie',
      'relationship': 'me'
    }
  }
}
\$\endgroup\$
  • \$\begingroup\$ Thank you for your answer I've tried this approach, but it returns "'list' object has no attribute 'values'". I've just modified your code to work for a list of dicts, and it works! Thank you very much for the help. \$\endgroup\$ – Daniel Hansen Mar 9 '18 at 21:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.