来自 csv python 的分层 JSON

Hierarchical JSON from csv python

我有一个以 csv 格式构建的数据集,如下所示:

Name,code,count
Adam,01,48
Bill,01,32
Chris,01,4
Carl,01.01,5
Dave,01.01,1
David,01.01,1
Eric,01.01.01,26
Earl,01.01.01.01,2
Frank,01.01.01.01,2
Greg,01.01.01.02,2
Harold,01.01.01.03,7
Ian,01.01.01.03,3
Jack,01.01.01.03,1
John,01.01.01.04,10
Kyle,01.01.01.04,2
Larry,01.01.03.01,3
Mike,01.01.03.01.01,45
Nick,01.01.03.01.01.01,1
Oliver,01.01.03.01.01.02,16
Paul,01.01.03.01.01.03,23

我想在 python 中制作字典,其中 "name" 和 "count" 是 key:value 对(这很容易),但我想整理基于 "code" 数字的层次结构。即 01.01 是 01 的 child,我不确定如何遍历数据来实现这一点。我最终想对整个结构进行 json 转储,但让我失望的是如何构建层次结构。非常感谢任何帮助。

我猜您想做一些标准的树结构,您可以在其中访问树结构,并在使用路径访问时自动创建缺少的节点。

像这样。

class Node:
    def __init__( self, parent=None ):
        self.parent = parent
        self.store = {}
        self.children = {}

    def create_child( self, child_name ):
        self.children[ child_name ] = Node( self )

    #ancestry_line is a list of names
    def recursive_get_child( self, ancestry_line_names ):
        if len(ancestry_line_names) == 0:
            return self
        else:
            next_ancestor = ancestry_line_names[0]
            other_ancestors = ancestry_line_names[1:]
            if next_ancestor not in self.children:
                self.create_child( next_ancestor )
            return self.children[ next_ancestor ].recursive_get_child( other_ancestors )

您需要做的就是创建一个根节点,并根据路径从中访问正确的节点。

root = Node()
for name, code, count in some_data_iterator():
    ancestry_line = code.split(".")
    root.get( ancestry_line ).store[ name ] = count

然后您可以在 Node 中创建一个方法,将 Node 结构转换为可用于在 json 中转储的纯字典结构。

下面的代码片段找到了一棵树的所有节点,而不是实际创建一个节点。 Python 中的树和链表实现效率低下 (Beazley)。

from itertools import groupby
import csv

with open('csvfile.csv') as f:
    reader = csv.DictReader(f)

groups = groupby(reader, key=lambda row: row['code'])
nodes = {code: {item['Name']: item['count'] for item in group} for code,group in groups}

{'01': {'Adam': '48', 'Bill': '32', 'Chris': '4'},
 '01.01': {'Carl': '5', 'Dave': '1', 'David': '1'},
 '01.01.01': {'Eric': '26'},
 '01.01.01.01': {'Earl': '2', 'Frank': '2'},
 '01.01.01.02': {'Greg': '2'},
 '01.01.01.03': {'Harold': '7', 'Ian': '3', 'Jack': '1'},
 '01.01.01.04': {'John': '10', 'Kyle': '2'},
 '01.01.03.01': {'Larry': '3'},
 '01.01.03.01.01': {'Mike': '45'},
 '01.01.03.01.01.01': {'Nick': '1'},
 '01.01.03.01.01.02': {'Oliver': '16'},
 '01.01.03.01.01.03': {'Paul': '23'}}

在 Python 中实现树结构的一种简单而优雅的方法使用递归 defaultdict:

import csv, json
from collections import defaultdict

def tree():
    return defaultdict(tree)

d = tree()

with open('data.txt', 'rb') as f:
    reader = csv.reader(f, delimiter=',')

    for name, code, count in list(reader)[1:]:
        path = code.split('.')
        iter_node = d
        for node in path:
            iter_node = iter_node[node]
        iter_node['values'][name] = count

print json.dumps(d, indent=2)

{
  "01": {
    "values": {
      "Chris": "4", 
      "Bill": "32", 
      "Adam": "48"
    },
    "01": {
      "values": {
        "Dave": "1", 
        "Carl": "5", 
        "David": "1"
      },
      "03": {
        "01": {
          "01": {
            "02": {
              "values": {
                "Oliver": "16"
              }
            }, 
            "03": {
              "values": {
                "Paul": "23"
              }
            }, 
            "01": {
              "values": {
                "Nick": "1"
              }
            }, 
            "values": {
              "Mike": "45"
            }
          }, 
          "values": {
            "Larry": "3"
          }
        }
      }, 
      "01": { 
        "values": {
          "Eric": "26"
        }, 
        "02": {
          "values": {
            "Greg": "2"
          }
        }, 
        "03": {
          "values": {
            "Harold": "7", 
            "Ian": "3", 
            "Jack": "1"
          }
        }, 
        "01": {
          "values": {
            "Earl": "2", 
            "Frank": "2"
          }
        },
        "04": {
          "values": {
            "John": "10", 
            "Kyle": "2"
          }
        }
      }
    }
  }
}