2013-02-12 3 views
0

с помощью Python 3.3.0, я создал "словарь" из CSV-файла (заголовок: ID;Col1;Col2;Col3;Col4;Col5):Python3: создать выборочный копию словаря в качестве нового словаря

ID;Col1;Col2;Col3;Col4;Col5 
15345;1;1;nnngngn;vhrhtnz;latest 
12345;12;8;gnrghrtthr;tznhltrnhklr;latest 
90834;3;4;something;nonsens;latest 
12345;34;235;dontcare;muhaha;oldone 

с кодом

file = "test.csv" 
csv_file = csv.DictReader(open(file, 'r'), delimiter=';', quotechar='"') 

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

cewl = {} 
for row in csv_file: 
    if row['ID'] == '12345': 
    cewl.update(row) 
print(cewl) 

Выход есть:

{'ID': '12345', 'Col1': '34', 'Col2': '235', 'Col3': 'dontcare', 'Col4': 'muhaha', 'Col5': 'oldone'} 

Моя проблема: только вторая строка с ID = 12345, копируется, первый опущен, я не знаю, почему.

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

cewl = [] 
for row in csv_file1: 
if row['ID'] == '12345': 
    cewl.append(row) 
print(cewl) 

Выход:

[{'Col3': 'gnrghrtthr', 'Col2': '8', 'Col1': '12', 'Col5': 'latest', 'Col4': 'tznhltrnhklr', 'ID': '12345'}, 
{'Col3': 'dontcare', 'Col2': '235', 'Col1': '34', 'Col5': 'oldone', 'Col4': 'muhaha', 'ID': '12345'}] 

Я не знаю, почему это ISN 't работая путем копирования в новый словарь ... там не похоже, что метод .add или .append для dictreader.

Как скопировать данные в новый словарь без каких-либо строк?

+0

Словарь - это сопоставление; решить, хотите ли вы, чтобы ID ('12345') сопоставлялся с двумя или более разными частями данных, как в вашем примере, и в этом случае вы можете сопоставить идентификатор со списком словарей, содержащих различные сопоставления значений для ключей 'Col1', Col2' и т. Д. ИЛИ что-то вроде списка кортежей '(ID, Col1, Col2 и т. Д.)'. Подумайте о своих структурах данных, прежде чем писать какой-либо код. –

ответ

1

Каков ожидаемый выход? Поведение совершенно нормально для dict; вы выбрали вместо значения для каждого ключа с новым значением.

Если вы хотите значения быть списки значений для каждой соответствующей строки, то проще использовать defaultdict с list завода:

from collections import defaultdict 

cewl = defaultdict(list) 

for row in csv_file: 
    if row['ID'] == '12345': 
     for k, v in row.items(): 
      cewl[k].append(v) 

print(cewl) 

Это выходы:

defaultdict(<class 'list'>, {'Col1': ['12', '34'], 'ID': ['12345', '12345'], 'Col2': ['8', '235'], 'Col5': ['latest', 'oldone'], 'Col4': ['tznhltrnhklr', 'muhaha'], 'Col3': ['gnrghrtthr', 'dontcare']}) 

A defaultdict является подклассом dict, поэтому print(cewl['Col1']) напечатает ['12', '34'].

При использовании .update() вы сделать это эффективно:

for k, v in row.items(): 
    cewl[k] = v 

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

Если вы хотите отфильтровать только строки, соответствующие определенным критериям ID, добавление их в список просто отлично.Затем вы перебираем совпавших результатов для их обработки:

for row in cewl: 
    # do something with matched row 

или вы можете построить генератор фильтр, который обернуть вокруг DictReader() сделать фильтрацию для вас, так что вам не нужно, чтобы построить список в памяти :

def rowfilter(reader, id): 
    for row in reader: 
     if row['ID'] == id: 
      yield row 

for row in rowfilter(csv_file, '12345'): 
    # do something with matched row 
+0

@ dacoda: объект сопоставления python отображает ключ в значение * one *. Поэтому 'somedict ['a'] = 1', за которым следует' someddict ['a'] = 2' означает, что вы * заменили * значение для ключа '' a''. Мое предлагаемое решение дает вам значение списка, и мы добавляем элементы в этот список, когда мы их находим. Я не уверен, что вы понимаете, как работают python-сопоставления. –

+0

Если вы ожидаете список словарей, тогда используйте свой список и добавьте в него строки. –

+0

@ dacoda: Я был в состоянии прочитать ваш комментарий просто отлично, пожалуйста, не редактируйте ответы, когда комментарий будет делать. Я хочу, чтобы вы дали мне * точный * ожидаемый результат, а не то, что вы уже разместили (потому что «что-то вроде этого, но другого» не ясно). –

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