Как создать дерево JSON из табличной иерархии в Python - PullRequest
0 голосов
/ 14 сентября 2011

Я уверен, что есть элегантный способ сделать это на Python (или на толчке, Javascript), но для жизни я не вижу этого ...

У меня есть CSVфайл формы:

ID, Name, Description
A, A-name,
A100, A100-name, A100-desc
A110, A110-name, A110-desc
A111, A111-name, A111-desc
A112, A112-name, A112-desc
A113, A113-name, A113-desc
A120, A120-name, A120-desc
A131, A131-name, A131-desc
A200, A200-name, A200-desc
B, B-name,
B100, B100-name, B100-desc
B130, B130-name, B130-desc
B131, B131-name, B131-desc
B140, B140-name, B140-desc

, и я хочу создать иерархическую структуру JSON, чтобы я мог визуализировать данные в theJIT .

var json = {  
  "id": "aUniqueIdentifier",  
  "name": "usually a nodes name",  
  "data": {  
    "some key": "some value",  
    "some other key": "some other value"  
   },  
  "children": [ *other nodes or empty* ]  
}; 

Мой план былсопоставить идентификатор с идентификатором, имя с именем, описание с данными.desc и организовать иерархию так, чтобы:

  • Корень являлся родительским для A, а B
  • A являлся родительским для A100.и A200
  • A100 является родительским для A110, а A120
  • A110 является родительским для A111, A112 и A113
  • B является родительским для B100
  • B100 является родительскимB130 и B140
  • B130 является родителем B131

Существует также патологический случай в противном случае регулярное упорядочение по ID, где A100 является родителем A131 (ожидаемый A130 не являетсянастоящее время).

Я надеялся найти элегантное решение Python для этого, но в настоящий момент он побеждает меня, даже игнорируя патологичный случай ...

1 Ответ

2 голосов
/ 14 сентября 2011

Это делает это ...

import csv
import json

class Node(dict):
    def __init__(self, (nid, name, ndescr)):
        dict.__init__(self)
        self['id'] = nid
        self['name'] = name.lstrip() # you have badly formed csv....
        self['description'] = ndescr.lstrip()
        self['children'] = []

    def add_node(self, node):
        for child in self['children']:
            if child.is_parent(node):
                child.add_node(node)
                break
        else:
            self['children'].append(node)

    def is_parent(self, node):
        if len(self['id']) == 4 and self['id'][-1] == '0':
            return node['id'].startswith(self['id'][:-1])
        return node['id'].startswith(self['id'])

class RootNode(Node):
    def __init__(self):
        Node.__init__(self, ('Root', '', ''))

    def is_parent(self, node):
        return True

def pretty_print(node, i=0):
    print '%sID=%s NAME=%s %s' % ('\t' * i, node['id'], node['name'], node['description'])
    for child in node['children']:
        pretty_print(child, i + 1)

def main():
    with open('input.csv') as f:
        f.readline() # Skip first line
        root = RootNode()
        for node in map(Node, csv.reader(f)):
            root.add_node(node)

    pretty_print(root)
    print json.dumps(root)

if __name__ == '__main__':
    main()
...