Могу ли я указать несколько ключей для вложенного словаря в одном цикле for вместо использования вложенных циклов for? - PullRequest
0 голосов
/ 07 мая 2019

У меня есть словарь словарей, который выглядит так:

d = {names: {IDs: {"constant": value, "some_list": []}}

Где каждое имя потенциально имеет несколько идентификаторов, и каждый идентификатор имеет постоянное значение и список переменной длины с конкретными строками в качестве ключей. Моя цель состоит в том, чтобы напечатать имена и IDS, когда список имеет заданную длину. Я знаю, как это сделать с помощью вложенных циклов:

for n in d:
    for i in d[n]:
        num = len(d[n][i]["some_list"])
        if num > 5:
            print "Warning %s %s has %i items" % (n, i, num)

У меня нет причины, по которой вышесказанное неприемлемо, оно работает и доступно для чтения.

Мне любопытно, если есть способ указать n и i в одном цикле for. Следующие ошибки по разным причинам:

for one in d.values().keys():  # fails as list has no attribute keys
for one.keys() in d.values():  # fails as functions can't be assigned to calls

Следующее сгенерирует список кортежей, которые затем могут быть повторены, но все же содержит два цикла for внутри понимания и потребует дополнительного цикла через новый список для печати:

new_list = [(n, i) for n in d for i in d[n] if len(d[n][i]["some_list"] > 5] 

Разве нельзя обойтись без использования 2 для циклов? или есть трюк, который я пропускаю?

Ответы [ 2 ]

1 голос
/ 07 мая 2019

Со словарем уровня 2+ вы всегда будете иметь где-то вложенные циклы, независимо от того, скрыты они внутри функции или выражены явно.

Что вы можете сделать, это изменить структуру словаря, чтобы он использовал ключ из нескольких частей (в кортеже):

tupleDict = { (name,idx):content for name,idd in d.items() for idx,content in idd() }

print(tupleDict)

# {('name1', 'ID11'): {'constant': 1, 'some_list': [1]}, ('name1', 'ID12'): {'constant': 2, 'some_list': [2]}, ...}

Затем вы можете применить фильтры без вложенных циклов, используя эту альтернативную структуру:

min5Lists = { k:v for k,v in tupleDict.items() if len(v['some_list'])>5 }
0 голосов
/ 07 мая 2019

Здесь много проблем.Во-первых, ваш синтаксис неправильный.

d = {names: {IDs: {"constant": value, "some_list": []}} 

должен быть больше похож на

d = {"names": {"IDs": {"constant": "some_value", "some_list": []}}}

Если каждое имя может иметь несколько идентификаторов и может быть несколько имен, покажите более полный пример:

d = {
   "name1": {
      "id1": {"constant": "value1", "some_list": []},
      "id2": {"constant": "value2", "some_list": []},
      },
   "name2": {
      "idA": {"constant": "valueA", "some_list": []},
      "idB": {"constant": "valueB", "some_list": []},
      },
}

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

Если бы вы могли сделать это за один циклбыло бы очень трудно понять и поддерживать.

...