2016-03-02 2 views
-2

У меня есть файл в формате:словарь ошибка в Python 2.7

0000 | a1_1,a3_2 | b2_1, b3_2 
0001 | a1_3 | b4_1 

, и я пытаюсь создать словарь, который имеет

{ 'a1' : set(['b2', 'b3', 'b4']), 'a3': set(['b2', 'b3']) } 

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

def get_ids(row, col): 
    ids = set() 
    x = row.strip().split('|') 
    for a in x[col].split(','): 
     ids.add(a.split('_')[0]) 
    return ids 

def add_to_dictionary(funky_dictionary,key, values): 
    if key in funky_dictionary: 
     funky_dictionary[key].update(values) 
    else: 
     funky_dictionary[key] = values 


def get_dict(input_file): 
    funky_dictionary = {} 
    with open(input_file,'r') as ip: 
     for row in ip: 
      a_ids = get_ids(row,1) 
      b_ids = get_ids(row,2) 
      for key in a_ids: 
       add_to_dictionary(funky_dictionary,key,b_ids) 
    return funky_dictionary 

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

Для приведенного выше примера ожидаемое значение a3 будет set(['b2', ' b3']) Однако с кодом, я получаю set(['b2', ' b3', 'b4'])

Я не могу понять, что случилось с кодом. Любая помощь?

+0

Вы не собираетесь получать утечки памяти в нормальном коде Python. Можете ли вы отформатировать словарь во втором кодовом блоке как словарь Python? Неясно, что представляет этот формат. – Kupiakos

+0

Там вы идете. Зачем голосовать? Btw. Я делаю это для файла размером 400 МБ. Не должно было возникнуть проблем с файлами. У меня достаточно ресурсов. – Ayush

+0

Было больше просмотров, чем только я. Подумайте о том, что я не был никем. Еще одна вещь, которая может помочь улучшить вопрос, - это пример вывода по сравнению с ожидаемым. – Kupiakos

ответ

1

Проблема заключается в том, что многие значения вашего словаря на самом деле являются ссылками на те же set экземпляры. В ваших примерах данных, когда обрабатывается первая строка, 'a1' и 'a3' оба отображаются на один и тот же объект set (содержащий 'b2' и 'b3'). Когда вы обрабатываете вторую строку и вызываете update на этом наборе с помощью ключа 'a1', вы также увидите добавленное значение через 'a3', так как оба значения являются ссылками на тот же set.

Вам необходимо изменить код, чтобы каждое значение было отдельным объектом set. Я предлагаю, чтобы избавиться от add_to_dictionary и только с помощью словаря собственного setdefault method, как это:

for key in a_ids: 
    funky_dictionary.setdefault(key, set()).update(b_ids) 

Этого код всегда начинается с новым пустым набором для нового ключа, и всегда обновляет его с новыми значениями (а не добавив ссылку на b_ids, установленную непосредственно в словаре).

+0

Да, это была ошибка. Кажется настолько тривиальным, когда вы, наконец, поймаете его. Большое спасибо! – Ayush