【问题标题】:Nested dictionary issue嵌套字典问题
【发布时间】:2018-07-09 22:48:15
【问题描述】:

我需要创建一个接受 CSV 文件并返回嵌套字典的程序。外部字典的键应该是每行中的第一个值,从第二个开始(以便省略具有列名的行)。外部字典中每个键的值应该是另一个字典,我在下面解释。

内部字典的键应该是列名,而值应该是每一行中该列对应的值。

例子:

对于这样的 CSV 文件:

column1, column2, column3, column4
4,12,5,11
29,47,23,41
66,1,98,78

我想以这种形式打印出数据:

my_dict = {
'4': {'column1':'4','column2':'12', 'column3':'5', 'column4':'11'},
'29': {'column1':'29', 'column2':'47', 'column3':'23', 'column4':'41'},
'66': {'column1':'66', 'column2':'1', 'column3':'98', 'column4':'78'}
}

到目前为止我得到的最接近的(甚至还没有接近):

import csv
import collections

def csv_to_dict(file, delimiter, quotechar):

list_inside_dict = collections.defaultdict(list)
with open(file, newline = '') as csvfile:
    reader = csv.DictReader(csvfile, delimiter=delimiter, quotechar=quotechar)
    for row in reader:
        for (k,v) in row.items(): 
            list_inside_dict[k].append(v)
return dict(list_inside_dict)

如果我尝试使用上面的示例 CSV 文件 delimiter = ","quotechar = "'" 运行该函数,它会返回以下内容:

{'column1': ['4', '29', '66'], ' column2': ['12', '47', '1'], ' column3': ['5', '23', '98'], ' column4': ['11', '41', '78']}

此时我迷路了。我试图改变:

list_inside_dict = collections.defaultdict(list)

list_inside_dict = collections.defaultdict(dict)

然后简单地更改每个键的值,因为我无法追加到字典中,但这一切都变得非常混乱。所以我从头开始,发现我到达了同一个地方。

【问题讨论】:

    标签: python python-3.x dictionary nested


    【解决方案1】:

    您可以使用字典理解:

    import csv
    with open('filename.csv') as f:
      header, *data = csv.reader(f)
      final_dict = {a:dict(zip(header, [a, *b])) for a, *b in data}
    

    输出:

    {'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'}, 
     '29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'}, 
     '66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
    

    【讨论】:

      【解决方案2】:

      您可以使用pandas 完成该任务。

      >>> df = pd.read_csv('/path/to/file.csv')
      >>> df.index = df.iloc[:, 0]
      >>> df.to_dict('index')
      

      不确定为什么要复制第一列的值,但如果您不这样做,上述简化为:

      >>> pd.read_csv('/path/to/file.csv', index_col=0).to_dict('index')
      

      【讨论】:

        【解决方案3】:

        这类似于this answer,但是,我相信它可以更好地解释。

        import csv
        
        with open('filename.csv') as f:
            headers, *data = csv.reader(f)
            output = {}
            for firstInRow, *restOfRow in data:
                output[firstInRow] = dict(zip(headers, [firstInRow, *restOfRow]))
            print(output)
        

        它的作用是遍历文件中的数据行,其中第一个值作为索引,后面的值在列表中。然后通过压缩标题列表和值列表来设置输出字典中的索引值。那条output[first] = ... 行与写output[firstInRow] = {header[1]: firstInRow, header[2]: restOfRow[1], ...} 相同。

        输出:

        {'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'}, 
        '29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'}, 
        '66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
        

        【讨论】:

          【解决方案4】:

          zips 可以得到你想要的。

          我们可以为 csv 使用字符串,而不是文件。只需将该部分替换为文件即可。

          给定:

          s='''\
          column1, column2, column3, column4
          4,12,5,11
          29,47,23,41
          66,1,98,78'''
          

          你可以这样做:

          import csv 
          
          data=[]
          for row in csv.reader(s.splitlines()):  # replace 'splitlines' with your file
              data.append(row)
          
          header=data.pop(0)
          col1=[e[0] for e in data]
          di={}
          for c,row in zip(col1,data):
              di[c]=dict(zip(header, row))
          

          然后:

          >>> di
          {'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'}, 
           '29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'}, 
           '66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
          

          在 Python 3.6+ 上,字典将保持插入顺序。早期的 Python 不会。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-08-23
            • 2021-11-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-29
            • 2021-12-11
            相关资源
            最近更新 更多