Lukas
Lukas

Reputation: 53

How to loop over a nested json structure in Python?

I am having trouble getting key values in a JSON.

import json


packages = [
  [
    {
      "name": "a2ps",
      "installs": 61423
    },
    {
      "name": "aravis",
      "installs": 61424
    },
    {
      "name": "arangodb",
      "installs": 61425
    }
  ],
  [
    {
      "name": "argon2",
      "installs": 61420
    },
    {
      "name": "archivemount",
      "installs": 61421
    },
    {
      "name": "archivemail",
      "installs": 61422
    }
  ]
]

package_names = [package_name['name'] for package_name in packages]
package_installs = [package_installs['installs'] for package_installs in packages]

As you can see, I am trying to get the packages name and install numbers but when I run the code I get an error. This is the full traceback:

Traceback (most recent call last):
  File "/Users/me/Documents/json.py", line 1, in <module>
    import json
  File "/Users/me/Documents/json.py", line 35, in <module>
    package_names = [package_name['name'] for package_name in packages]
  File "/Users/me/Documents/json.py", line 35, in <listcomp>
    package_names = [package_name['name'] for package_name in packages]
TypeError: list indices must be integers or slices, not str

But when I do the following, I do the get the names and installs but for only for the specified package.


package_names = [package_name['name'] for package_name in packages[0]]
package_names2 = [package_name['name'] for package_name in packages[1]]
package_installs = [package_installs['installs'] for package_installs in packages[0]]
package_installs2 = [package_installs['installs'] for package_installs in packages[1]]
print(package_names, package_names2, package_installs, package_installs2)

Output:

['a2ps', 'aravis', 'arangodb'] ['argon2', 'archivemount', 'archivemail'] [61423, 61424, 61425] [61420, 61421, 61422]

Upvotes: 0

Views: 474

Answers (5)

Jadli
Jadli

Reputation: 860

   packages = [[{'name': 'a2ps', 'installs': 61423}, {'name': 'aravis', 'installs': 61424}, {'name': 'arangodb', 'installs': 61425}], [{'name': 'argon2', 'installs': 61420}, {'name': 'archivemount', 'installs': 61421}, {'name': 'archivemail', 'installs': 61422}]]

nameInstallDic= {package_name['name']: package_name['installs'] for ls in packages for package_name in ls}
name=nameInstallDic.keys()
installs=nameInstallDic.values()
name=list(name)
installs=list(installs)
print('name: ',name)
print('installs: ',installs)

outPut: name: ['aravis', 'argon2', 'archivemail', 'a2ps', 'archivemount', 'arangodb']
installs: [61424, 61420, 61422, 61423, 61421, 61425]

or you can use another below approach

iterObj = iter(packages)

package_names = [package_name['name'] for package_name in [*next(iterObj), *next(iterObj)]]

print('package_names :', package_names)

iterObj2 = iter(packages)
package_installs = [package_install['installs'] for package_install in [*next(iterObj2), *next(iterObj2)]]
print('package_installs:', package_installs)

Output : package_names : ['a2ps', 'aravis', 'arangodb', 'argon2', 'archivemount', 'archivemail'] package_installs: [61423, 61424, 61425, 61420, 61421, 61422]

Upvotes: 0

ruohola
ruohola

Reputation: 24038

You were close, since you have a list of dict lists, you need to use two loops in the list comprehensions:

packages = [[{'name': 'a2ps', 'installs': 61423}, {'name': 'aravis', 'installs': 61424}, {'name': 'arangodb', 'installs': 61425}], [{'name': 'argon2', 'installs': 61420}, {'name': 'archivemount', 'installs': 61421}, {'name': 'archivemail', 'installs': 61422}]]

package_names = [package_name['name'] for ls in packages for package_name in ls]
package_installs = [package_install['installs'] for ls in packages for package_install in ls]

print(package_names)
print(package_installs)

Output:

['a2ps', 'aravis', 'arangodb', 'argon2', 'archivemount', 'archivemail']
[61423, 61424, >61425, 61420, 61421, 61422]

As you can see, you also don't need to use the json package for anything, these are just regular plain Python lists and dicts.

Upvotes: 1

Rik
Rik

Reputation: 1987

Like others mentioned, you need another layer:

package_names = [package_name['name'] for package in packages for package_name in package ]

Upvotes: 0

Jay Mody
Jay Mody

Reputation: 4033

The top TWO levels of your json are list, so when you do:

[package_name['name'] for package_name in packages]

You forgot that each element in packages is another list, not the package_name dictionary.

Instead try a double list comprehension:

package_names = [package_name['name'] for sub_packages in packages for package_name in sub_packages]
package_installs = [package_install['installs'] for sub_packages in packages for package_install in sub_packages]

Upvotes: 1

Barmar
Barmar

Reputation: 780974

You need nested loops to process the nested lists.

package_names = []
package_installs = []
for sublist in packages:
    for package in sublist:
        package_names.append(package['name'])
        package_installs.append(package['installs'])

Upvotes: 0

Related Questions