Python: скрытие значений пустых ключей json в операторе печати

Это моя первая программа на Python, получающая данные через файлы json для создания научных ссылок:

....
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 

Пока он работает нормально, за исключением того, что я не знаю, как скрыть значения ключей из оператора print, когда ключи не имеют значения (т. Е. В файле json такого ключа нет для одной конкретной цитаты).

Например, некоторые из научных ссылок не имеют идентификатора ключа / значения "Pubmed" (pmd). Вместо того, чтобы печатать "Pubmed: " с пустым значением, я хотел бы избавиться от них обоих:

# 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: 

Я попробовал следующее (не печатать pmd, если значение пусто), но это не работает:

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

Спасибо за вашу помощь.

3 ответа

Вы можете сделать следующее:

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)

Используемая здесь магия находится внутри get функция, которую нам предоставляет объект dict. Таким образом, вы можете определить значение по умолчанию в случае, если в вашем dict отсутствует определенный ключ (ваш объект JSON - это не что иное, как dict в Python). При использовании этого вы можете избежать написания большого количества ifи до сих пор есть несколько расширяемый и безопасный метод для создания вашей строки. Кроме того, вы не запрашиваете свой диктат дважды, как описано здесь.

Если ваш результат JSON будет содержать больше полей в будущем, вам просто нужно добавить их в этот набор здесь

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

и они будут добавлены к строке в порядке их перечисления.

Подробнее о встроенных функциях dict смотрите здесь.

Вы сделали почти правильно! за исключением встроенного, если заявления должны иметь условие else,

изменить этоprint(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ', pbm, sep="")в print(nom,', ', tit, '. ', jou, '.', dat, '. Pubmed: ' if len(pbm)!=0 else "", pbm if len(pbm)!=0 else "", sep="")

Поэтому, если нет ключа Pubmed, pbm будет "", а len(pbm) равно 0.(Вы также можете использовать pbm=""). В этих случаях " Pubmed: 'value' " не будет напечатано.

Я думаю, что лучший / самый чистый способ будет использовать "длинный" if/else:

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

Вы можете сделать это немного чище, используя строку формата:

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

Или объедините строку формата с троичной ... if ... else ...:

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

Лично я бы пошел со вторым вариантом.

Другие вопросы по тегам