2016-02-04 4 views
0

Я пытаюсь прочитать несколько файлов с очень похожими данными. Каждая строка этих данных имеет accessor_key и значение, ассоциированное с ней. Я пытаюсь создать словарь с ключом accessor_key в качестве словарного слова и как значение словаря - список всех значений, прочитанных до сих пор.Python: Список как ключ в словаре -

Мой код выглядит следующим образом:

with open(ind_file, "r") as r: 
    for line in r: 
    nline = line.strip() 
    spl = nline.split(",") 
    if agg_d.has_key(spl[0]): 

     key = spl[0] 
     val = spl[1] 
     dummy = agg_d[key] 
     dummy.append(val) 
     agg_d[key] = dummy 
     print key, agg_d[key] 

    else: 
     print "Something is wrong" 
     print agg_d 
     print spl[0] 
     print spl[1] 

Как вы можете видеть, что я хочу значение, чтобы получить больше каждый раз, (увеличивается список в размере от 1 на каждой итерации) и сохраните его обратно в словарь. Однако, когда я запускаю эту программу, все ключи в словаре принимают значение списка.

Так, например, в начале программы словаря:

agg_d = {'some_key': [], 'another_key': []} 

После запуска, как только она становится:

agg_d = {'some_key': ['1'], 'another_key': ['1']} 

Когда это должно быть просто:

agg_d = {'some_key': ['1'], 'another_key': []} 

EDIT: Я нашел работу вокруг, которую искал. Я просто сделал:

with open(ind_file, "r") as r: 
for line in r: 
    nline = line.strip() 
    spl = nline.split(",") 
    if agg_d.has_key(spl[0]): 

    key = spl[0] 
    val = spl[1] 
    dummy = agg_d[key] 
    ad = dummy[:] 
    ad.append(val) 
    agg_d[key] = ad 
    print key, agg_d[key] 

    else: 
    print "Something is wrong" 
    print agg_d 
    print spl[0] 
    print spl[1] 

Но я все равно хотел бы знать, почему это происходит вообще. Является ли «манекен» ссылкой на все значения словаря? Я запускаю это с Python 2.7.

+0

показать, как вы создаете пустой словарь. вероятно, вы назначаете один и тот же пустой список для обоих ключей. – furas

+2

Sidenote: 'dict.has_key' устарел и медленнее, чем простой общий метод проверки наличия ключа в' dict'; change 'if agg_d.has_key (spl [0]):' to 'if spl [0] в agg_d:', который делает то же самое быстро и более Pythonically для загрузки. – ShadowRanger

ответ

1

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

Если вы инициализируете agg_d с новым списком на ключ, проблема должна исчезнуть. Вы можете быть в состоянии сделать это с помощью словаря понимания:

>>> keys = ["a", "b", "c"] 
>>> agg_d = {k:[] for k in keys} 
>>> agg_d["a"].append(1) 
>>> agg_d 
{'a': [1], 'c': [], 'b': []} 

В качестве альтернативы, в зависимости от ваших потребностей, вы можете инициализировать каждую запись по требованию, как вы сталкиваетесь каждый ключ при чтении файла.

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

+0

Да, это то, что я подозревал. Я инициализировал только один список для всех переменных. – Sood

2

Является ли «фиктивный» ссылкой на все значения словаря? Я запускаю это с Python 2.7.

Да. Вы добавили ссылку на список, и может быть несколько ссылок на тот же список, который вы наблюдали. Чтобы проиллюстрировать это просто, попробуйте следующее:

dummy = [1,2,3]   # creates a list object and assigns reference to the name 'dummy' 
d = dict() 
d['some key'] = dummy # creates the key 'some key' in the dictionary and assigns its value as the reference to the name 'dummy' 

dummy.append(4)   # mutates the list referred to by name 'dummy' 
         # at this point, all references to that object have mutated similarly 

print d['some key'] 

Вы увидите следующий вывод:

>>> [1,2,3,4] 

Ваш обходной путь в порядке, но вы могли бы улучшить:

with open(ind_file, "r") as r: 
    for line in r: 
     spl = line.strip().split(",") 
     key, val = spl[0], spl[1] 
     if key in agg_d: 
     agg_d[key] = agg_d[key][:].append(val) 
     print key, agg_d[key] 
     else: 
     print "Something is wrong" 
     print agg_d 
     print spl[0] 
     print spl[1] 

agg_d[key] = agg_d[key][:].append(val) 

Это не мутирует ваш список dummy на месте и переназначает значение в словаре. Также избегает некоторых ненужных переменных, таких как nline и ad и dummy.

0

Проблема заключается в том, что по умолчанию Python просто добавляет ссылку на список как значение dict, а не сам список. Таким образом, значения dict фактически представляют собой набор указателей на один и тот же объект. Вам нужно явно скопировать список, используя либо фиктивный [:], как вы предлагаете в комментарии, или copy.deepcopy(), чтобы быть более явным.

Смежные вопросы