Создание вложенного словаря с циклом for - PullRequest
0 голосов
/ 24 октября 2018

У меня есть файл CSV, и я пытаюсь создать вложенный словарь, который выглядит следующим образом:

contacts = {"Tom": {"name": "Tom Techie",
                    "phone": "123 123546",
                    "email": "tom@tom.fi",
                    "skype": "skypenick"},

            "Mike": {"name": "Mike Mechanic",
                     "phone": "000 123546",
                     "email": "mike@mike.fi",
                     "skype": "-Mike-M-"}}

и т. Д.

И вот что я написал:

file = open("csv","r")
d = {}
for i in file:

    f = i.strip()
    x = f.split(";")

    if x[4] != "":
        d.update({x[0] : {"name":x[1],
                      "phone":x[2],
                      "email":x[3],
                      "skype":x[4]}})

    else:
        d.update ({x[0] : {"name": x[1],
                       "phone": x[2],
                       "email": x[3]}})

Однако он печатает dict как обычный словарь с обновлениями в качестве ключей, когда они должны быть такими, как указано выше.

EDIT: Первые строки csv:

key;name;phone;email;skype
Tom;Tom Techie;123 123546;tom@tom.fi;skypenick
Mike;Mike Mechanic;000 123456;mike@mike.fi;-Mike-M-
Archie;Archie Architect;050 987654;archie@archie

Ответы [ 4 ]

0 голосов
/ 24 октября 2018

Мне нравится ответ pandas, но если вам не нужна сторонняя библиотека, используйте встроенный модуль csv:

import csv
from pprint import pprint

D = {}
with open('csv',newline='') as f:
    r = csv.DictReader(f,delimiter=';')
    for line in r:
        name = line['key']
        del line['key']
        D[name] = dict(line)

pprint(D)

Вывод:

{'Archie': {'email': 'archie@archie',
            'name': 'Archie Architect',
            'phone': '050 987654',
            'skype': None},
 'Mike': {'email': 'mike@mike.fi',
          'name': 'Mike Mechanic',
          'phone': '000 123456',
          'skype': '-Mike-M-'},
 'Tom': {'email': 'tom@tom.fi',
         'name': 'Tom Techie',
         'phone': '123 123546',
         'skype': 'skypenick'}}
0 голосов
/ 24 октября 2018

Вы можете использовать zip () для достижения своей цели:

file = """key;name;phone;email;skype
Tom;Tom Techie;123 123546;tom@tom.fi;skypenick
Mike;Mike Mechanic;000 123456;mike@mike.fi;-Mike-M-
Archie;Archie Architect;050 987654;archie@archie""".splitlines()

d = {}
h = None
for i in file: # works the same for your csv-file
    # first row == header, store in h
    if h is None:
        h = i.strip().split(";")[1:]
        continue # done for first row

    x = i.strip().split(";")

    # zip pairs the read in line with the header line to get tuples
    # wich are fed into the dict constructor that creates the inner dict
    d[x[0]] = dict(zip(h,x[1:]+[""])) # no default for skype

    # use this instead if you want the skype key always present with empty default
    # d[x[0]] = dict(zip(h,x[1:]+[""]))  

print(d)

zip () отбрасывает элементы более длинного списка - вы не будетедля этого нужны какие-либо проверки.

Вывод:

{'Tom':   {'name': 'Tom Techie', 'phone': '123 123546', 
           'email': 'tom@tom.fi', 'skype': 'skypenick'}, 
 'Mike':   {'name': 'Mike Mechanic', 'phone': '000 123456', 
            'email': 'mike@mike.fi', 'skype': '-Mike-M-'}, 
 'Archie': {'name': 'Archie Architect', 'phone': '050 987654', 
            'email': 'archie@archie'}}

Если вы используете закомментированную строку, данные получат значение по умолчанию '' для скайпа - работает только b / cскайп - последний элемент разделенной линии

0 голосов
/ 24 октября 2018

Вы можете использовать словесное понимание!Предполагая, что данные похожи на this here...

with open("df.csv", "r") as file:
  d = {x.split(";")[0]:{
      "name": x.split(";")[2], 
      "phone": x.split(";")[3],
      "email": x.split(";")[1], 
      "skype": x.split(";")[4][:-1] # Slice off trailing newline
  } for x in file}
  d.pop("")

Мы хотим открывать файлы, используя with, когда это возможно, чтобы извлечь выгоду из управления контентом Python.См. https://www.python.org/dev/peps/pep-0343/ для фундаментального понимания оператора with.

Поскольку ключ "" появляется только один раз в начале csv, мы можем выдвинуть его в конце и избежать выполнениясравнение на каждой итерации.Диктовое понимание выполняет то же, что вы хотели достичь с помощью d.update.

Подробнее о понимании: https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions

Редактировать: рефакторинг для удаления повторяющихся вызовов .split может выглядеть как-токак это:

def line_to_dict(x, d):
  x = x.split(";")
  d[x[0]] = {
      "name": x[2], 
      "phone": x[3],
      "email": x[1], 
      "skype": x[4][:-1] # Slice off trailing newline
  }

with open("df.csv", "r") as file:
  d = {}
  for x in file:
    line_to_dict(x, d)
  d.pop("")
0 голосов
/ 24 октября 2018

Вы можете использовать pd.read_csv() и to_dict():

import pandas as pd

contacts = pd.read_csv('test.csv', sep=';').set_index('key').to_dict(orient='index')

Выход:

{'Tom': {'name': 'Tom Techie', 'phone': '123 123546', 'email': 'tom@tom.fi', 'skype': 'skypenick'}, 'Mike': {'name': 'Mike Mechanic', 'phone': '000 123456', 'email': 'mike@mike.fi', 'skype': '-Mike-M-'}, 'Archie': {'name': 'Archie Architect', 'phone': '050 987654', 'email': 'archie@archie', 'skype': nan}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...