0

This is my first Python program, getting data through json files to build scientific citations:

....
js = json.loads(data)

# here is an excerpt of my code:
print("Journal articles:")
for art in js['response']['docs']:
   stuff = art['docType_s']
   if not stuff == 'ART': continue
   tit = art['title_s'][0]
   nom = art['authFullName_s'][0]
   jou = art['journalTitle_s']
   dat = art['producedDateY_i']
   try:
       pbm = art['pubmedId_s']
   except (KeyError, NameError):
       pbm = ""
   print(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ', pbm, sep="")

# sample output: J A. Anderson, Looking at the DNA structure, Nature, 2018. Pubmed: 3256988 

It works fine so far, except that I don't know how to hide key values from the print statement when keys have no value (ie. there is no such key in the json file for one specific citation).

For example, some of the scientific citations have no "Pubmed" ID key/value (pmd). Instead of printing "Pubmed: " with a blank value, I would like to get rid of both of them:

# Desired output (when pbm key is missing from the JSON file):
# J A. Anderson, Looking at the DNA structure, Nature, 2018.
# NOT: J A. Anderson, Looking at the DNA structure, Nature, 2018. Pubmed: 

I tried the following (don't print pmd if value is empty) but it doesn't work:

print('. Pubmed: ', pbm if pbm != "")

Thanks for your help.

Laurent J
  • 25
  • 6

3 Answers3

0

You could do the following:

js = json.loads(data)

print("Journal articles:")
for art in js['response']['docs']:
    stuff = art['docType_s']
    if not stuff == 'ART': continue
    tit = art.get('title_s', None)[0]
    nom = art.get('authFullName_s', None)[0]
    jou = art.get('journalTitle_s', None)
    dat = art.get('producedDateY_i', None)
    pbm = art.get('pubmedId_s', None)

    l = []
    for e in (tit, nom, jou, dat, pbm):
        if e:
            if e is pbm:
                l.append('Pubmed: ' + str(e))
            else:
                l.append(str(e))
    pub = ', '.join(l).strip(', ')

    print(pub)

The magic used here lies inside the get function which the dict object provides us. This way you can define a default value in case a specific key doesn't exist in your dict (your JSON object is nothing but a dict in Python). In using that you can avoid writing lots of ifs and still have a somewhat expandable and safe method to build up your string. Plus, you don't query your dict twice as explained here.

In case your JSON result will contain more fields in the future, you just have to add them inside this set here

...
for e in (tit, nom, jou, dat, pbm): #<-- insert more values here
...

and they will be appended to the string in the order you list them.

For more on built-in dict functions see here.

Arno-Nymous
  • 495
  • 3
  • 14
  • What if you want to add more specific keys like the Pubmed one? @Arno-Nymous I would like to add a "vol" key (volume_s), but also a second author key named "nom2" which has an index: `nom = art.get('authFullName_s', None)[1]` Like "pmd", these 2 keys might not always be in the JSON dictionary. – Laurent J Jul 12 '18 at 20:39
0

You Did almost right! except, Inline if statements need to have else condition so,

change this print(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ', pbm, sep="") to print(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ' if len(pbm)!=0 else "", pbm if len(pbm)!=0 else "", sep="")

Therefore, if there is no Pubmed key, pbm will be "" and len(pbm) is 0.(You can also use pbm=""). On these cases " Pubmed: 'value' " won't be printed.

  • I tried to do the same for another value (nom2 = 2nd author) but it didn't work because nom2 is an indexed value: `nom2 = art['authFullName_s'][1]` I tried this: `print(nom, ', ' if len(nom2)!=0 else "", vol if len(nom2)!=0 else "", ', ', tit, '. ', jou, '.', dat, '. Pubmed: ' if len(pbm)!=0 else "", pbm if len(pbm)!=0 else "", sep="") ` @Reaganrewop – Laurent J Jul 12 '18 at 20:40
  • Did you use try and except for nom2 check whether the value is present or not, like you did for pbm....... And i don't understand the logic here, you need to remove the vol variable if nom2 is None? – Reaganrewop Jul 13 '18 at 04:09
  • Oops, I meant `print(nom, ', ' if len(nom2)!=0 else "", nom2 if len(nom2)!=0 else "", ', ', tit, '. ', jou, '.', dat, '. Pubmed: ' if len(pbm)!=0 else "", pbm if len(pbm)!=0 else "", sep="")` - and yes, I use try and except but forgot to add "IndexError". It's now working, thanks! I guess I spent too much time on it, I should have taken a break ;) – Laurent J Jul 13 '18 at 06:57
-1

I think the best/cleanest way would be using a "long" if/else:

if pbm:
    print(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ', pbm, sep="")
else:
    print(nom,', ', tit, '. ', jou, '.', dat, ', sep="")

You could make this a bit cleaner using a format string:

if pbm:
    print("%s, %s, %s. %s Pubmed: %s" % (nom, tit, jou, dat, pbm))
else:
    print("%s, %s, %s. %s" % (nom, tit, jou, dat))

Or combine a format string with a ternary ... if ... else ...:

print("%s, %s, %s. %s%s" % (nom, tit, jou, dat, ((" Pubmed: " + pbm) if pbm else "")))

Personally, however, I'd go with the second option.

tobias_k
  • 81,265
  • 12
  • 120
  • 179