1

My goal is to iterate through every element in classes and add the value of class in classes into a new list.

JSON Structure:

{
    "images": [
      {
        "classifiers": [
          {
            "classes": [
              {
                "class": "street",
                "score": 0.846
              },
              {
                "class": "road",
                "score": 0.85
              }
            ]
          }
        ]
      }
   ]
}

In the above JSON example, the new list should contain:

{'street','road'}

I tried to iterate over json_data['images'][0]['classifiers']['classes'] and for each one list.append() the value of class.

list = list()
def func(json_data):
    for item in json_data['images'][0]['classifiers']['classes']:
        list.append(item['class'])
    return(list)

I am receiving a TypeError which is:

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

What I am getting from this TypeError is that it attempts to add a string to the list but list.append() does not accept a string as a paramet. I need to somehow convert the string into something else.

My question is what should I convert the string into so that list.append() will accept it as a parameter?

James
  • 1,928
  • 3
  • 13
  • 30
  • 1
    Thanks for showing us your input & expected output. Now show us the code you've written to do this, and explain where you're stuck. – PM 2Ring Jul 25 '17 at 18:14
  • I keeep getting TypeError: list indices must be integers or slices, not str and using that error and trying things on StackOverflow to fix that error are not working. – James Jul 25 '17 at 18:16
  • 2
    Please include the full traceback as an edit too. – roganjosh Jul 25 '17 at 18:17
  • Thanks for adding some code. "classifiers" is a list, so you need to use a numeric index to get at its contents, just like you did with "images". – PM 2Ring Jul 25 '17 at 18:17
  • 3
    `classifiers` and `classes` are also lists. `json_data['images'][0]['classifiers'][0]['classes']:` – roganjosh Jul 25 '17 at 18:18
  • What code do I need to get this to work. I tried a numeric index and got the same error. Can you please post an answer to the question and I will also mark it as correct if it is. – James Jul 25 '17 at 18:20
  • The code that roganjosh just showed you will get the list of dicts in "classes". – PM 2Ring Jul 25 '17 at 18:23
  • It is working but it is returning ['street','road','yellow color','green color'] not {'street','road','yellow color','green color'}... How can I make it not do that? And does someone want to post it as an answer? @PM2Ring – James Jul 25 '17 at 18:26
  • 1
    `return set(lst)` I think. If that is what you expect I'll have a go at writing an answer on my phone - always fun - so you can close this. – roganjosh Jul 25 '17 at 18:29
  • Tracing through JSON to find the correct sequence of dict keys and list indices can be painful. It can help a bit if you do `json.dumps(json_data, indent=4)`. Or you can use [this code](https://stackoverflow.com/a/41778581/4014959) I wrote a few months ago. – PM 2Ring Jul 25 '17 at 18:38
  • What does this mean? Doing `if ['images'][0]['classifiers'][0]["classes"] not in json_data:` Gives me `TypeError: string indices must be integers` @PM2Ring @roganjosh – James Jul 25 '17 at 19:14
  • `['images']` is a list containing a single string. `['images'][0]` gets the first item in that list, which is the string `'images'`. So `['images'][0]['classifiers']` is the same as `'images'['classifiers']`, and Python is telling you that it doesn't make sense because string indices must be integers. You could do (for example) `'images'[3]`, that would give you the `'g'` in `'images'`. I _suspect_ you were really wanting to do `if "classes" not in json_data['images'][0]['classifiers'][0]:` – PM 2Ring Jul 25 '17 at 19:55
  • Yes but when I do that it says list index out of range – James Jul 25 '17 at 20:27
  • @PM2Ring Here is the other question more explained https://stackoverflow.com/questions/45313266/if-json-key-exists-else – James Jul 25 '17 at 20:52
  • @PM2Ring I just rewrote the question. I hope it is better! If you think it is and you want to could you please upvote it! Thanks! I already figured it out but wanted to make it better in case someone else needs help! – James Sep 10 '17 at 18:57
  • @roganjosh Please look at the above comment – James Sep 10 '17 at 18:58

1 Answers1

3

The first issue is that classifiers is also a list, so you need an additional index to get at classes. This will work:

for item in json_data['images'][0]['classifiers'][0]['classes']:

Second, you want the result as a set not a list, so you can do: return set(lst). Note that sets are unordered, so don't expect the ordering of items to match that of the list.

roganjosh
  • 12,594
  • 4
  • 29
  • 46
  • How do I make it ordered? – James Jul 25 '17 at 18:38
  • Why do you need it to be both a set and ordered before we go down that route? – roganjosh Jul 25 '17 at 18:40
  • It actully does not need to be a set. It can be a list – James Jul 25 '17 at 18:40
  • I just need it to have the {} – James Jul 25 '17 at 18:51
  • What does this mean? Doing `if ['images'][0]['classifiers'][0]["classes"] not in json_data:` Gives me `TypeError: string indices must be integers` – James Jul 25 '17 at 19:14
  • @Brendan `['street','road','yellow color','green color']` is a list of strings, `{'street','road','yellow color','green color'}` is a set of strings. Python sets don't maintain the order of their items. So if you "just need it to have the {}" then you need a set. Note that JSON doesn't support sets. – PM 2Ring Jul 25 '17 at 19:48
  • Here is the other question more explained https://stackoverflow.com/questions/45313266/if-json-key-exists-else – James Jul 25 '17 at 20:52