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\$

closed as off-topic by Peilonrayz, t3chb0t, Imus, Toby Speight, Stephen Rauch Apr 6 '18 at 12:26

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Peilonrayz, t3chb0t, Imus, Toby Speight, Stephen Rauch
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\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.