Преобразовать csv в список словарей в python

#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-файле. Таким образом, код работает, но не для случайных чисел столбцов. В любом случае, вы дали мне идею, и это важно.