#python #list #csv #dictionary
#python #Список #csv #словарь
Вопрос:
Я получил файл CSV, где первая строка — это заголовки, затем другие строки — это данные в столбцах.
Я использую python для анализа этих данных в список словарей
Обычно я бы использовал этот код:
def csv_to_list_of_dictionaries(file):
with open(file) as f:
a = []
for row in csv.DictReader(f, skipinitialspace=True):
a.append({k: v for k, v in row.items()})
return a
но поскольку данные в одном столбце хранятся в словаре, этот код не работает (он разделяет пары ключ: значение в этом словаре
итак, данные в моем csv-файле выглядят следующим образом:
col1,col2,col3,col4
1,{'a':'b', 'c':'d'},'bla',sometimestamp
словарь из этого создается следующим образом: {col1:1, col2:{'a':'b', col3: 'c':'d'}, col4: 'bla'}
В результате я хочу получить: {col1:1, col2:{'a':'b', 'c':'d'}, col3: 'bla', col4: sometimestamp}
Комментарии:
1. В CSV не существует тонны стандартов, но ваш ввод выглядит нарушенным. Если вы хотите включить запятые в один столбец, наиболее распространенным решением является заключение всего значения в кавычки, например
1,"{'a':'b', 'c':'d'}",'bla',sometimestamp
. Возможно, вы сможете указатьcsv
модулю обрабатывать фигурные скобки как кавычки, но исправление источника также стоит рассмотреть.2. Я думаю
quotechar
, может быть только один символ; вы не сможете сделать что-то вродеcsv.DictReader(f, quotechar="{}")
. И на самом деле, это тоже не то, что вы хотите, поскольку фигурные скобки должны быть частью проанализированного результата. Можете ли вы предварительно обработать файл и заменить{
на"{
и}
на}"
?
Ответ №1:
Не используйте модуль csv используйте регулярное выражение для извлечения полей из каждой строки. Затем создайте словари из извлеченных строк.
Пример файла:
col1,col2,col3,col4
1,{'a':'b', 'c':'d'},'bla',sometimestamp
2,{'a':'b', 'c':'d'},'bla',sometimestamp
3,{'a':'b', 'c':'d'},'bla',sometimestamp
4,{'a':'b', 'c':'d'},'bla',sometimestamp
5,{'a':'b', 'c':'d'},'bla',sometimestamp
6,{'a':'b', 'c':'d'},'bla',sometimestamp
.
import re
pattern = r'^([^,]*),({.*}),([^,]*),([^,]*)$'
regex = re.compile(pattern,flags=re.M)
def csv_to_list_of_dictionaries(file):
with open(file) as f:
columns = next(f).strip().split(',')
stuff = regex.findall(f.read())
a = [dict(zip(columns,values)) for values in stuff]
return a
stuff = csv_to_list_of_dictionaries(f)
In [20]: stuff
Out[20]:
[{'col1': '1',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'},
{'col1': '2',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'},
{'col1': '3',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'},
{'col1': '4',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'},
{'col1': '5',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'},
{'col1': '6',
'col2': "{'a':'b', 'c':'d'}",
'col3': "'bla'",
'col4': 'sometimestamp'}]
Комментарии:
1. но это не решает проблему получения {‘a’:’b’, ‘c’:’d’} только во второй столбец и не разделяет его между вторым и третьим столбцами
2. @marquillo — вы правы, я, должно быть, не обращал внимания. Извините за это. Пожалуйста, посмотрите мою правку.
3. хорошо, итак, я расширил шаблон регулярных выражений, и он сработал для меня, спасибо
4. @marquillo — как расширить шаблон регулярных выражений? Вы можете добавить к моему ответу, если хотите.
5. ваш шаблон регулярных выражений был рассчитан ровно на четыре «столбца», поэтому мне пришлось подготовить его для того количества столбцов, которое у меня есть в моем csv-файле. Таким образом, код работает, но не для случайных чисел столбцов. В любом случае, вы дали мне идею, и это важно.