2012-05-12 3 views
2

Я написал код для выполнения простого форматирования csv, но я знаю, что это не так хорошо, как могло бы быть.Рекомендации по форматированию CSV Python

Вот вход

1,a 
1,b 
1,c 
2,d 
2,e 
3,a 
3,d 
3,e 
3,f 

Вот выход я хочу

['1','a','b','c'] 
['2','d','e'] 
['3','a','d','e','f'] 

Это код, который я написал

import csv 
input = csv.reader(open('book1.csv')) 
output = open('output.csv', 'w') 
job=[0,0] 
for row in input: 
    if row[0] == job[1]: 
     job.append(row[1]) 
    else: 
     print(job) 
     #output.write(",".join(job)) 
     job[1] = row[0] 
     job = [job[0], job[1]] 
     job.append(row[1]) 

Это выход

[0,0] 
[0, '1', 'a', 'b', 'c'] 
[0, '2', 'd', 'e'] 

Вопросы у меня следующие

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

Я спрашиваю, потому что я хотел бы стать намного лучше при написании кода, а не просто взломать его вместе. Любые ответы были бы высоко оценены! Заранее спасибо

ответ

2

То, что вы пытаетесь сделать, это группировать второй столбец по первому столбцу. Python имеет инструмент для этого, itertools.groupby:

groups = itertools.groupby(input, key=operator.itemgetter(0)) 

является итератором с получением (key, group) кортежей, где key является первым элементом в строках, и каждый представляет собой group итератор линий в группе.

operator.itemgetter делает то же самое, что и синтаксис [] - получает указанный товар. operator.itemgetter(0) таких же, как:

def itemgetter_0(seq_or_mapping): 
    return seq_or_mapping[0] 

Чтобы извлечь значения и создавать списки, вы можете:

output = [[key] + map(operator.itemgetter(1), group) for key, group in groups] 

, который начинается каждый список с key, а затем извлекает второй элемент из каждой строки и добавляет их к списку.

Для примера входных данных, то выход будет:

[['1', 'a', 'b', 'c'], ['2', 'd', 'e'], ['3', 'a', 'd', 'e', 'f']] 
1

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

Попытка ответить на актуальные вопросы, которые вы задавали, здесь минимальные изменения, необходимые, чтобы сделать ваш код работать:

import csv 
input = csv.reader(open('book1.csv')) 
output = open('output.csv', 'w') 
job = [] 
for row in input: 
    if not job: # first row in input file 
     job = row 
    elif row[0] == job[0]: 
     job.append(row[1]) 
    else: 
     print(job) 
     #output.write(",".join(job)) 
     job = row 
if job: # emit the last job (if any) 
    print(job) 
+0

У меня есть основной вопрос о выполнении программы. Что касается последнего оператора if, если задание: print (job) «Почему он не печатает каждое задание, а только последнее?Мое предположение состоит в том, что код петли в строках до тех пор, пока он не закончится, а затем выполнит последние две строки, но я хотел бы попросить дважды проверить. – canyon289

+0

@ canyon289: последний оператор 'if' имеет отступы на том же уровне, что и оператор' for', который предшествует ему, поэтому он будет выполнен, когда цикл завершается. Однако, если он (и его сопровождающий 'print()') был отступом еще 4 пробела, то он будет выполнен для каждой строки ввода - не очень хорошая идея! Другой способ взглянуть на это: он делает то, что вы просили (хотел бы, чтобы код выводил последнее задание), попробуйте удалить эти 2 строки и посмотреть, что произойдет. –