Ответ 1
Во-первых, for key,value in dict1
не делает то, что вы хотите - он просто выполняет итерации по клавишам. Если вы хотите перебрать пару ключ-значение, вам нужно for key, value in dict1.items()
.
Между тем, похоже, что вы запрашиваете, это итерация блокировки, а не вложенная итерация? Если это так, вам нужна функция zip
:
for (k1, v1), (k2, v2) in zip(dict1.items(), dict2.items()):
# do something
Но обратите внимание, что упорядочение, которое это дает вам, фактически будет произвольным, потому что упорядочение dicts по своей сути произвольно. Итак, если вы довольны ('a', 'x')
, затем ('b', 'y')
и т.д., А также довольны ('a', 'y')
, тогда ('b', 'x')
, тогда zip
- это то, что вы хотите. Если нет, это не так.
(Если вы ожидали, что ваш dict
имеет некоторый собственный порядок, например порядок вставки или отсортированный порядок, или что-нибудь еще, вам придется использовать другой класс. Например, collections.OrderedDict
действует как словарь, но сохраняет порядок вставки.)
Если вам нужно что-то более сложное, где вы перемещаете итерацию по dict2
программно так, как вы не можете выразить в однострочном пространстве, вы всегда можете использовать протокол итерации вручную:
iter2 = iter(dict2.items())
for k1, v1 in dict1.items():
k2, v2 = next(iter2)
# do something
# maybe do another k2, v2 = next(iter2)
# maybe restart iter2 = iter(dict2.items())
# and so on
Как объясняют документы, когда next(iter2)
подходит к концу, он поднимет StopIteration
. Что, если вы этого не хотите? Может быть, вы хотите, как вы сказали в комментарии, начать заново? Вы можете решить это, поймав StopIteration
, или используя форму с двумя аргументами next
и проверку для часового. Например:
try:
k2, v2 = next(iter2)
except StopIteration:
iter2 = iter(dict2.items())
k2, v2 = next(iter2)
Или вы даже можете написать круговую итерационную оболочку:
def circular_iterate(iterable_factory):
while True:
yield from iterable_factory():
В Python 3.2 или более ранней версии вы должны заменить yield from
на внутренний цикл:
def circular_iterate(iterable_factory):
while True:
for value in iterable_factory():
yield value
И теперь:
iter2 = circular_iterate(dict2.items) # note, not dict2.items()
Если вы пытаетесь отслеживать больше, чем просто "текущую позицию", вам, вероятно, потребуется дополнительная структура данных. Например, если вы хотите пропустить все обнаруженные до сих пор клавиши, используйте set
для ключей, которые были просмотрены до сих пор, или set
ключей, которые не были видны:
seen_items_2 = set()
for k1, v1 in dict1.items():
for k2, v2 in dict2.items():
if k2 in seen_items_2:
continue
seen_items_2.add(k2)
# do something