Как Pythonic способ перебрать диктовку и списки? - PullRequest
2 голосов
/ 03 апреля 2012

У меня есть dict, который содержит несколько списков и некоторые dicts, как показано ниже.

Какой самый питонический способ перебрать этот dict и распечатать пары имен и адресов для каждого ключа dict верхнего уровня?

Спасибо

{
    'Resent-Bcc': [],
    'Delivered-To': [],
    'From': {'Name': 'Steve Watson', 'Address': 'steve.watson@example.org'},
    'Cc': [],
    'Resent-Cc': [],
    'Bcc': [ {'Name': 'Daryl Hurstbridge', 'Address': 'daryl.hurstbridge@example.org'},
             {'Name': 'Sally Hervorth', 'Address': 'sally.hervorth@example.org'},
             {'Name': 'Mike Merry', 'Address': 'mike.merry@example.org'},
             {'Name': 'Jenny Callisto', 'Address': 'jenny.callisto@example.org'}
           ],
    'To': {'Name': 'Darius Jedburgh', 'Address': 'darius.jedburgh@example.org'}
}

Ответы [ 5 ]

3 голосов
/ 03 апреля 2012

Используйте метод iteritems() на диктовке. Это ясно и легко понять: мне это кажется Pythonic. iteritems() также создает меньше временных элементов, чем items(), как упомянул в комментариях Преет Кукрети. Сначала исправьте ваши данные. Прямо сейчас, некоторые значения в dict верхнего уровня являются списками, а некоторые являются более dict:

# list
'Delivered-To': [],
# dict
'From': {'Name': 'Steve Watson', 'Address': 'steve.watson@example.org'},

Это означает, что вы должны проверить тип значения и действовать соответственно (и вы можете забыть проверить!). Сделайте ваши данные непротиворечивыми:

# list
'Delivered-To': [],
# also list
'From': [{'Name': 'Steve Watson', 'Address': 'steve.watson@example.org'}],

Это предотвратит странные ошибки, связанные с типами, в будущем. Поскольку Python является интерпретируемым языком, очень легко создавать ошибки типов и не замечать их, пока ваш код не будет запущен и не выйдет из строя. Постарайтесь сделать ваш код максимально безопасным для типов!

Тогда вы можете использовать что-то вроде этого:

for k, v in d.iteritems():
  for row in v:
    if "Name" in row and "Address" in row:
      print row["Name"], ":", row["Address"]
2 голосов
/ 03 апреля 2012

Один из способов состоит в том, чтобы превратить одиночные диктанты в список, содержащий диктанты.Тогда все записи могут обрабатываться одинаково

>>> D = {
...     'Resent-Bcc': [],
...     'Delivered-To': [],
...     'From': {'Name': 'Steve Watson', 'Address': 'steve.watson@example.org'},
...     'Cc': [],
...     'Resent-Cc': [],
...     'Bcc': [ {'Name': 'Daryl Hurstbridge', 'Address': 'daryl.hurstbridge@example.org'},
...              {'Name': 'Sally Hervorth', 'Address': 'sally.hervorth@example.org'},
...              {'Name': 'Mike Merry', 'Address': 'mike.merry@example.org'},
...              {'Name': 'Jenny Callisto', 'Address': 'jenny.callisto@example.org'}
...            ],
...     'To': {'Name': 'Darius Jedburgh', 'Address': 'darius.jedburgh@example.org'}
... }
>>> L = [v if type(v) is list else [v] for v in D.values()]
>>> [(d["Name"], d["Address"]) for item in L for d in item ]
[('Steve Watson', 'steve.watson@example.org'), ('Daryl Hurstbridge', 'daryl.hurstbridge@example.org'), ('Sally Hervorth', 'sally.hervorth@example.org'), ('Mike Merry', 'mike.merry@example.org'), ('Jenny Callisto', 'jenny.callisto@example.org'), ('Darius Jedburgh', 'darius.jedburgh@example.org')]

или версия с одним вкладышем

[(d["Name"], d["Address"]) for item in (v if type(v) is list else [v] for v in D.values())]
1 голос
/ 03 апреля 2012

Вероятно, лучше сохранить ваши данные простыми, сделав голый диктат списком из одного элемента, содержащего исходный диктет. В противном случае, вы просите сложнее протестировать код.

Я склонен отворачиваться от isinstance (foo, dict) и вместо этого использовать такие вещи, как: if getattr (d, 'iteritems'): вывести список (d.iteritems ())

... Это кажется мне более утонченным; это открывает двери для использования одного из множества заменителей диктата - вещей, которые действуют как диктат, но номинально не являются диктатом.

0 голосов
/ 03 апреля 2012
for key in header:
    if header[key] and type(header[key])==type([]):
        for item in header[key]:
            print (item)
    elif type(header[key])==type({}):
        print(header[key])

# this option is not the easiest to read, so I classify it as less "pythonic"       
l = [header[key] for key in header if header[key] and type(header[key])==type({})] + [header[key][i] for key in header if header[key] and type(header[key])==type([]) for i in range(len(header[key]))]
for item in l:
    print(item)

если вы ищете содержимое определенного заголовка, вы можете соответствующим образом изменить операторы if.Оба из этих примеров печатают словари, но могут быть легко адаптированы для печати определенных значений.

0 голосов
/ 03 апреля 2012
for i in dict:
   if 'Name' in dict[i]: 
      print (dict[i]['Name'],dict[i]['Address'])

это не будет работать для скрытой копии, находящейся в списке (сейчас она будет печатать только имена и адреса от и до). Вам также нужно печатать адреса скрытой копии?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...