2015-04-21 3 views
0

Я хочу, чтобы объединить два файла CSV на основе поля 1-ый один выглядит следующим образом:Python объединить CSV файлы с совпадающими Index

ID, field1, field2 
1,a,green 
2,b,white 
2,b,red 
2,b,blue 
3,c,black 

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

ID, field3 
1,value1 
2,value2 

Что Я хочу, чтобы это:

ID, field1, field2,field3 
1,a,green,value1 
2,b,white,value2 
2,b,red,value2 
2,b,blue,value2 
3,c,black,'' 

Я использую PyDev на затмение

import csv 

endings0=[] 
endings1=[] 
with open("salaries.csv") as book0: 
    for line in book0: 
     endings0.append(line.split(',')[-1]) 
     endings1.append(line.split(',')[0]) 

linecounter=0 


res = open("result.csv","w") 

with open('total.csv') as book2: 
    for line in book2: 
     # if not header line: 

     l=line.split(',')[0] 
     for linecounter in range(0,endings1.__len__()):    
      if(l == endings1[linecounter]): 
       res.writelines(line.replace("\n","") +','+str(endings0[linecounter])) 


print("done") 
+3

Хороший вопрос, но то, что вы пробовали до сих пор? – Kasramvd

+1

Рассматривали ли вы использование базы данных? – Eric

+0

Я обновляю вопрос, добавляя код, но мне не хватает последней строки (3, c, black, ''), и я не уверен, что это лучший способ сделать это. –

ответ

3

Есть куча вещей неправильно с тем, что вы делаете

  1. Вы должны действительнодействительно использовать классы в csv модуль для чтения и записи файлов CSV. Импортировать модуль недостаточно. Вам действительно нужно вызвать его функции

  2. Вы не должны набирать endings1.__len__(). Использовать len(endings1) вместо

  3. Вы не должны набирать for linecounter in range(0,len(endings1)).
    Используйте либо for linecounter, _ in enumerate(endings1),
    или еще лучше for end1, end2 in zip(endings1, endings2)

  4. Словарь является гораздо лучше структуры данных для поиска, чем пары параллельных списков. Процитировать pike:

    Если вы правильно выбрали структуры данных и организовали их, алгоритмы почти всегда будут очевидны.

Вот как я это сделать:

import csv 

with open('second.csv') as f: 
    # look, a builtin to read csv file lines as dictionaries! 
    reader = csv.DictReader(f) 

    # build a mapping of id to field3 
    id_to_field3 = {row['ID']: row['field3'] for row in reader} 

# you can put more than one open inside a with statement 
with open('first.csv') as f, open('result.csv', 'o') as fo: 
    # csv even has a class to write files! 
    reader = csv.DictReader(f) 
    res = csv.DictWriter(fo, fieldnames=reader.fieldnames + ['field3']) 

    res.writeheader() 
    for row in reader: 
     # .get returns its second argument if there was no match 
     row['field3'] = id_to_field3.get(row['ID'], '') 
     res.writerow(row) 
+0

Это сработало отлично, спасибо! –

0

У меня есть решение высокого уровня для вас. Отсоедините ваш первый CSV до dict1 идентификатор сопоставления с списком, содержащим список, содержащий поле1 и поле2. Отсоедините второй CSV до dict2.

для каждого (id, список) в dict1, do list.append(dict2.setdefault(id, '')). Теперь сериализуйте его обратно в CSV, используя любой сериализатор, который вы использовали раньше.

Я использовал словарь setdefault, потому что заметил, что ID 3 находится в первом CSV-файле, но не во втором.

+0

_ «какой бы сериализатор вы не использовали до» _ - это будет хорошо известный надежный интерфейс csv , поток сырого текста затем ... – Eric