2015-07-08 3 views
0

Я читаю в csv через csv.DictReader и пытаюсь заменить любые пустые значения значением None. DictReader, кажется, берет файл как экземпляр словарей, где каждая строка CSV является словарем (с которым я в порядке). Однако, когда я пытаюсь выполнить итерацию через строку/словарь по строке/словарю и заменить любые пустые значения ("") с None, я, кажется, отклеился. Я ранее написал это как список понимание, как это:условно заменить значение словаря python с пониманием

for row in data: 
     row = [None if not x else x for x in row] 

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

for row in data: 
     row.values() = [None if not x else x for x in row.values()} 

, но я просто получить SyntaxError: invalid syntax.. Я пробовал много других вещей (слишком много, чтобы перечислить здесь):

for row in data: 
     row = {k:None for k,v in row if v not v else v} 

но это похоже на ту же проблему.

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

{'colour': 'ab6612', 'line': '1', 'name': 'Baker', 'stripe': ''} 
    {'colour': 'f7dc00', 'line': '3', 'name': '', 'stripe': 'FFFFFF'} 

и, в идеале, в конечном итоге, как:

{'colour': 'ab6612', 'line': '1', 'name': 'Baker', 'stripe': None} 
    {'colour': 'f7dc00', 'line': '3', 'name': None, 'stripe': 'FFFFFF'} 
+0

спасибо всем, {к: (v, если не против еще None) для к, v в строке .items()} был именно тем, что я искал. Я не понимал, что могу вложить (v if v else None) вот так. Ценить это. – jhole89

ответ

2

Ваш вопрос в том, что вы меняете имя row ссылаться на новый словарь в цикл for, это ничего не изменит внутри вашего исходного списка/объекта DictReader - data.

Если данные список, вы должны перечислить через data и изменить словарь внутри данных (или сделать что ссылка новый словарь)

Пример -

for i,row in enumerate(data): 
    data[i] = {k:(v if v else None) for k,v in row.items()} 

Пример испытания -

>>> data = [{1:2 , 3:''},{4:'',5:6}] 
>>> for i,row in enumerate(data): 
...  data[i] = {k:(v if v else None) for k,v in row.items()} 
... 
>>> data 
[{1: 2, 3: None}, {4: None, 5: 6}] 

И поскольку вы используете класс DictReader, вы не можете напрямую изменить объект DictReader, поэтому вам следует создать новый список и добавить cha nged строка в новом списке (или объект DictWriter, предпочел бы объект DictWriter) -

Пример -

>>> newdata = [] 
>>> for row in data: 
...  newdata.append({k:(v if v else None) for k,v in row.items()}) 
+1

'newdata = [{k: (v if v else None) для k, v в row.items()} для строки в data]'? –

+0

Да, это также будет сделано. –

0

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

Try:

data = {k:(v if v else None) for k,v in data.items()} 

без для петли.

+1

данные являются списком, а не словарем, строка - это dict. –

+0

Ты чертовски прав, должен был внимательно прочитать вопрос. –

0

Если вы используете CSV и данные слишком большой, пожалуйста, используйте iteritems()

это сэкономит предотвратить большое поколение список, вызванных элементов() Try:

new_data=[]  
for row in data: 
    new_data.append({k:(v if v else None) for k,v in row.iteritems()}) 

если вы не понимаете, то следуйте этим простым для цикла:

for row in data: 
    for k,v in row.iteritems(): 
     if not v: 
      row[k]=None 

второй метод легко понять и не создает дополнительный список, который является лучшим для повышения производительности

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