2016-05-05 3 views
3

У меня есть файл CSV, который я читал как список словарей для каждой строки. Я хочу удалить все записи в списке с адресом электронной почты ''. Я пробовал:Удаление словаря из списка

#!/usr/bin/python 
import csv 


def import_users(location_of_file): 
    with open(location_of_file, 'r', newline='', encoding='utf-8-sig') as openfile: 
     reader = csv.DictReader(openfile) 
     for row in reader: 
      yield row 

def save_csv(data, location): 
    with open(location, 'w', newline='', encoding='utf-8-sig') as file: 
     fieldnames = ['EmailAddress', 'GivenName', 'Surname', 'Company', 'Department'] 
     writer = csv.DictWriter(file, fieldnames=fieldnames) 
     writer.writeheader() 
     for item in data: 
      writer.writerow(item) 



if __name__ == '__main__': 
    users = list(import_users('C:\Temp\Example.csv')) 
    for user in users: 
     if user['EmailAddress'] == '': 
      del user 
     else: 
      pass 
    save_csv(users, 'C:\Temp\Output.csv') 

Но мои результаты по-прежнему имеют записи без адреса электронной почты. Что я делаю не так?

+4

'дель user' * не * удалить элемент из списка, и вы не должны удалять элементы из списков, а итерацию над ними – jonrsharpe

ответ

4

Не изменяйте элементы списка, пока они раздражают их.

Вместо

for user in users: 
    if user['EmailAddress'] == '': 
     del user 
    else: 
     pass 

ли

users = filter(lambda user: user['EmailAddress'] != '', users) 
3

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

users = [user for user in users if user['EmailAddress'] != ''] 
+0

я бы предлагая изменить первые 'users' на' usersWithoutEmail', не стоит ничего иметь другое имя переменной (поскольку вы так или иначе создаете новый список) –

+1

Я бы сказал, что в этом случае нет оснований оставлять список оригинальных пользователей, поскольку он, по-видимому, не используется rwise. Еще лучший ответ может быть следующим: 'users = [пользователь для пользователя в import_users ('C: \ Temp \ Example.csv'), если пользователь ['EmailAddress]! =' ']', И никогда не генерирует переменную промежуточного списка пользователей – user3014097

+1

Я согласен с вашими аргументами. Тем не менее, это делает менее легким изменить код в будущем, если по какой-то причине вам нужны оба набора информации. –

5

Итерация по структуре данных, изменяемого плохая практика (и приведет к супер раздражающих ошибок). Поэтому вы должны составить другой список, содержащий только те элементы, которые вы хотите. Вы можете сделать это с помощью цикла:

users = list(import_users('C:\Temp\Example.csv')) 
filtered_users = [] 
for user in users: 
    if user['EmailAddress'] == '': 
     filtered_users.append(user) 
save_csv(filtered_users, 'C:\Temp\Output.csv') 

Или используя питон функцию фильтра:

users = list(import_users('C:\Temp\Example.csv')) 
filtered_users = filter(lambda user: user.get('EmailAddress') != '', users) 
save_csv(filtered_users, 'C:\Temp\Output.csv') 
5

Вам не нужно когда-либо создать список в памяти. Вы можете обойти генераторы и итераторы вместо:

if __name__ == '__main__': 
    users = import_users('C:/Temp/Example.csv') 
    save_csv((user for user in users if user['EmailAddress'] != ''), 
      'C:/Temp/Output.csv') 
+0

У меня есть несколько других вещей, которые мне нужно сделать с данными после этой начальной очистки. В частности, мне нужно запустить проверку по электронной почте, и, если существуют определенные элементы, мне нужно добавить значение к текущему словарю. Как бы я вытащил это из save_csv для выполнения? – user987654321

2

Вот решение, использующее pandas:

Пример данных:

enter image description here

import pandas as pd 
#Read csv data 
df = pd.read_csv('data.csv') 
#Get only the rows having email address 
dfo = df[pd.notnull(df['EmailAddress'])] 
#Save to a file 
dfo.to_csv('output.csv', index=False) 

Пример вывода:

enter image description here

+0

Я не знаком с использованием панд, но это выглядит довольно легко. Есть ли способ для итерации и обновления полей с помощью панд? Необходимо выполнить некоторые другие изменения, прежде чем я получу данные. – user987654321

+0

@ user987654321 да, вы можете делать все, о чем вы просите. Он имеет огромную функцию, пройдите 10-минутный учебник, вы сможете сделать больше. – Abbas

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