Как разобрать смешанный CSV-файл в Python?

#python #csv

#python #csv

Вопрос:

Я имею дело с CSV-файлом, похожим на этот

 foo; val1; position1
bar; name1; address1; phone_nbr1
bar; name2; address2; phone_nbr2
foo; val2; position2
bar; name3; address3; phone_nbr3
bar; name4; address4; phone_nbr4
bar; name5; address5; phone_nbr5
bar; name6; address6; phone_nbr6
foo; val3; position3
  

Излишне говорить, что я не могу изменить CSV.

Экземпляры, отображаемые в foo строках, отличаются от экземпляров со bar строками (обратите внимание, что у них даже разное количество полей)

Мне нужно просто прочитать эти данные, не нужно их записывать.

Моей первой идеей было разделить файл на два временных файла, а затем прочитать каждый из них отдельно с помощью a csv.DictReader , однако мне действительно не нравится этот подход.

Есть ли более простой способ сделать это? Я хотел бы, по возможности, избежать необходимости записывать файлы на диск.

Для справки, я использую Python2.7 на машине Solaris 10.

Ответ №1:

Вы можете собирать записи из a csv.reader в двух разных списках, в зависимости от их длины (или любого другого критерия, который вы используете для различения двух потоков):

 list1 = []
list2 = []
with open("input.csv", "rb") as f:
    for record in csv.reader(f, delimiter=";"):
        if len(record) == 3:
            list1.append(record)
        else:
            list2.append(record)
  

Ответ №2:

csv.reader() с этим проблем нет:

 import csv
foo = []
bar = []
with open("test.csv", 'r') as f:
    c = csv.reader(f, delimiter = ";")
    for row in c:
        if row[0] == "foo":
            foo.append(row[1:])
        elif row[0] == "bar":
            bar.append(row[1:])
print(foo)
print(bar)
  

результаты в

 [[' val1', ' position1'], [' val2', ' position2'], [' val3', ' position3']]
[[' name1', ' address1', ' phone_nbr1'], [' name2', ' address2', ' phone_nbr2'], [' name3', ' address3', ' phone_nbr3'], [' name4', ' address4', ' phone_nbr4'], [' name5', ' address5', ' phone_nbr5'], [' name6', ' address6', ' phone_nbr6']]
  

Ответ №3:

Как насчет простого использования str.split в каждой строке?

 items = line.split(";")
  

Затем, если первый элемент в items списке — foo вы делаете что-то одно, а если bar вы делаете что-то другое.

Ответ №4:

Тот факт, что строки разные, не является проблемой для csv module, но вам придется анализировать содержимое строки по-разному в зависимости от первой «ячейки».

Пример кода:

 with open(input_file, 'rb') as fin:
    c = csv.reader(fin)
    for line in c:
         if line[0] == 'foo':
              # do some treatment
         elif line[0] == 'bar':
              # do something else
    c.close()
  

Ответ №5:

Из вашего вопроса неясно, чего вы на самом деле хотите достичь, но я не уверен, что вам нужен модуль csv здесь.

 for row in myfile.readlines():
    cols = [r.strip() for r in row.split(';')]
    if (cols[0] == "foo"):
        # Do something for foo
    elif (cols[0] == "bar"):
        # Do something for bar
  

Ответ №6:

Как насчет чего-то вроде:

 foos = []
bars = []
for line in csv.reader(open("file.csv","rb"), delimiter=";"):
  if line[0] == "foo":
    foos.append(Foo(line[1], line[2]))
  else:
    bars.append(Bar(line[1], line[2], line[3]))
  

Предполагая, что у вас есть класс a Foo и a Bar , принимающий остальные ячейки строки в качестве аргументов.