2016-08-05 1 views
3

Я перебираю список кортежей и список строк. Строки являются идентификаторами для элементов в списке. У меня есть словарь, который имеет идентификаторы строк как ключи и имеет изначально пустой список для каждого значения. Я хочу добавить что-то из списка кортежей в каждый ключ. Упрощенная версия того, что я делаю:Python for loop, добавляющий к каждой клавише в словаре

tupleList = [("A","a"),("B","b")] 
stringList = ["Alpha", "Beta"] 
dictionary = dict.fromkeys(stringList, []) # dictionary = {'Alpha': [], 'Beta': []} 
for (uppercase, lowercase), string in zip(tupleList, stringList): 
    dictionary[string].append(lowercase) 

Я бы ожидать, что это даст dictionary = {'Alpha': ['a'], 'Beta': ['b']}, но вместо этого я считаю, что {'Alpha': ['a', 'b'], 'Beta': ['a', 'b']}. Кто-нибудь знает, что я делаю неправильно?

+0

не должен строчным всегда быть вторым пунктом в кортеже, поскольку я сопоставление (верхний регистр, нижний регистр) против tupleList? –

+0

Плохо, я понял свою ошибку после публикации, извините. – Luis

ответ

4

Ваша проблема заключается в том, что вы разделяете список между двумя ключами по ссылке.

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

Вместо этого вы должны использовать defaultdict, в основном это dict, который создает новые значения, если они не существуют, и извлекает их, если они это делают (и удаляет необходимо для if/else при вставке элемента, чтобы проверить, существует ли он уже). Это очень полезно в таких ситуациях:

from collections import defaultdict 

tupleList = [("A","a"),("B","b")] 
stringList = ["Alpha", "Beta"] 
dictionary = defaultdict(list) # Changed line 
for (uppercase, lowercase), string in zip(tupleList, stringList): 
    dictionary[string].append(lowercase) 
+2

Вместо словаря = defaultdict (lambda: []) 'вы также можете написать' dictionary = defaultdict (list) ', который я считаю более читаемым. –

+0

Спасибо, это действительно намного лучше :) –

2

Проблема заключается в том, что когда вы вызываете dict.fromkeys и передаете ему список как элемент по умолчанию для каждого ключа, python использует тот же список, списки не являются неизменяемыми, поэтому одно изменение в списке влияет на него везде, на которое оно ссылается, что вы может обойти это, чтобы вызвать dict.fromkeys без каких-либо аргументов, это устанавливает значения по умолчанию как None, тогда у вас есть инструкция if, чтобы проверить, является ли она None и инициализирует два разных списка. а затем вы добавите этот список, если он не является ником (когда он уже существует).

tupleList = [("A","a"),("B","b")] 
stringList = ["Alpha", "Beta"] 
dictionary = dict.fromkeys(stringList) # dictionary = {'Alpha': [], 'Beta': []} 
for (uppercase, lowercase), string in zip(tupleList, stringList): 
    #print(id(dictionary[string])) uncomment this with your previous code 
    if dictionary[string] is None: 
     dictionary[string] = [lowercase] 
    else: 
     dictionary[string].append(lowercase)