Axl
Axl

Reputation: 33

Can't Go Past First Dict In JSON File

I'm trying to iterate through a JSON file to search for specific parts and print out that portion of the file. But my code only works for the first dict in the file, anything past that will have my code print out that the part of the JSON file doesn't exit. Here is the JSON file:

[
{
    "Name": "Debian",
    "Version": "9",
    "Install": "apt",
    "Owner": "SPI",
    "Kernel": "4.9"
},
{
    "Name": "Ubuntu",
    "Version": "17.10",
    "Install": "apt",
    "Owner": "Canonical",
    "Kernel": "4.13"
},
{
    "Name": "Fedora",
    "Version": "26",
    "Install": "dnf",
    "Owner": "Red Hat",
    "Kernel": "4.13"
},
{
    "Name": "CentOS",
    "Version": "7",
    "Install": "yum",
    "Owner": "Red Hat",
    "Kernel": "3.10"
},
{
    "Name": "OpenSUSE",
    "Version": "42.3",
    "Install": "zypper",
    "Owner": "Novell",
    "Kernel": "4.4"
},
{
    "Name": "Arch Linux",
    "Version": "Rolling Release",
    "Install": "pacman",
    "Owner": "SPI",
    "Kernel": "4.13"
},
{
    "Name": "Gentoo",
    "Version": "Rolling Release",
    "Install": "emerge",
    "Owner": "Gentoo Foundation",
    "Kernel": "4.12"
}

]

Here is my Code:

import json

jsonfile = raw_input("Choose a json file: ")
type(jsonfile)

name = input("Type in the name: ")
type(name)

with open (jsonfile) as myfile:
   data = myfile.read()

obj = json.loads(data)

for i in obj:
  if i["Name"] == name:
     print(i["Version"])
     break
  else:
     print("Title not found")
     break

So say I enter the name "Debian" I get the version number just fine. But if I type in "Fedora" for example, I get the "Title not found" portion of my code. Which means that the name wasn't in the JSON file but it is. Any help would be appreciated.

Upvotes: 2

Views: 66

Answers (3)

user2314737
user2314737

Reputation: 29317

With break you're exiting immediately the for loop as soon as one element doesn't match name, hence the code works only for the first match.

This is how one could write a loop with a break statement

found = False
for i in obj:
    if i["Name"] == name:
        found = True
        break

if found:
    print(i["Version"])
else:
    print("Title not found")

If the loop is inside a function you could simply use return in place of break

def search(obj, name):
    for i in obj:
        if i["Name"] == name:
            return i["Version"]
    return "Title not found"

But the pythonic way to implement this would be:

next((i["Version"] for i in iter(obj) if i["Name"] == name), "Title not found")

next will stop after the first match as well.

Example:

obj= [
{
    "Name": "Debian",
    "Version": "9"
},
{
    "Name": "Ubuntu",
    "Version": "17.10"
},
{
    "Name": "Fedora",
    "Version": "26"
}]

name = "Fedora" 
next((i["Version"] for i in iter(obj) if i["Name"] == name), "Title not found")
# Out:
# '26'

Upvotes: 0

sorrat
sorrat

Reputation: 923

Your loop always ends on the first iteration.
Corrected version:

# ...
for i in obj:
    if i["Name"] == name:
        print(i["Version"])
        break
else:
    print("Title not found")

http://book.pythontips.com/en/latest/for_-_else.html

Upvotes: 0

DirtyBit
DirtyBit

Reputation: 16772

For the sake of simplicity:

s = [
      {
        "Name": "Debian",
        "Version": "9",
        "Install": "apt",
        "Owner": "SPI",
        "Kernel": "4.9"
      },
      {
        "Name": "Ubuntu",
        "Version": "17.10",
        "Install": "apt",
        "Owner": "Canonical",
        "Kernel": "4.13"
      },
      {
        "Name": "Fedora",
        "Version": "26",
        "Install": "dnf",
        "Owner": "Red Hat",
        "Kernel": "4.13"
      },
      {
        "Name": "CentOS",
        "Version": "7",
        "Install": "yum",
        "Owner": "Red Hat",
        "Kernel": "3.10"
      },
      {
        "Name": "OpenSUSE",
        "Version": "42.3",
        "Install": "zypper",
        "Owner": "Novell",
        "Kernel": "4.4"
      },
      {
        "Name": "Arch Linux",
        "Version": "Rolling Release",
        "Install": "pacman",
        "Owner": "SPI",
        "Kernel": "4.13"
      },
      {
        "Name": "Gentoo",
        "Version": "Rolling Release",
        "Install": "emerge",
        "Owner": "Gentoo Foundation",
        "Kernel": "4.12"
      }
]

Using list-comprehension:

search = 'Fedora'

print([x['Version'] for x in s if x['Name'] == search])

OUTPUT:

['26']

Explanation:

search = 'Fedora'

for elem in s:                      # for each elem in the list
    if elem['Name'] == search:      # check if the Name is what you're looking for
        print(elem['Version'])      # print the Version if it is

OUTPUT:

26

Upvotes: 1

Related Questions