【问题标题】:Creating a nested dictionary with for loop使用 for 循环创建嵌套字典
【发布时间】:2019-03-29 06:46:58
【问题描述】:

我有一个 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]}})

但是,当它们应该像上面所说的那样时,它将字典打印为普通字典,并将更新作为键。

编辑: 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

【问题讨论】:

  • 您的问题没有足够的信息来 a) 运行代码,b) 重现问题,c) 帮助您。
  • 您至少应该提供 csv 文件的前几行
  • 编辑简历的第一行以打开帖子

标签: python python-3.x csv dictionary


【解决方案1】:

您可以使用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}}

【讨论】:

    【解决方案2】:

    我喜欢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'}}
    

    【讨论】:

      【解决方案3】:

      您可以使用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'}}
      

      如果您使用注释行,Skype 的数据将获得默认值 '' - 仅适用于 b/c skype 是拆分行的最后一个元素

      【讨论】:

        【解决方案4】:

        您可以使用字典推导!假设数据类似于

        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 的上下文管理中受益。有关with 语句的基本理解,请参阅https://www.python.org/dev/peps/pep-0343/

        由于"" 键只在 csv 的头部出现一次,我们可以在末尾弹出它,避免在每次迭代时执行比较。 dict 理解可以完成您想要使用 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("")
        

        【讨论】:

          猜你喜欢
          • 2021-07-25
          • 2019-09-30
          • 2022-01-03
          • 2021-12-03
          • 1970-01-01
          • 2020-11-02
          • 2020-09-13
          • 2016-06-08
          • 2017-01-03
          相关资源
          最近更新 更多