将冗余数组转换为dict(或JSON)?

时间:2016-05-20 02:54:48

标签: python arrays json list

假设我有一个数组:

[['a', 10, 1, 0.1],
 ['a', 10, 2, 0.2],
 ['a', 20, 2, 0.3],
 ['b', 10, 1, 0.4],
 ['b', 20, 2, 0.5]]

我想要dict(或JSON):

{
    'a': {
        10: {1: 0.1, 2: 0.2},
        20: {2: 0.3}
    }
    'b': {
        10: {1: 0.4},
        20: {2: 0.5}
    }
}

这项任务有什么好方法或一些图书馆吗? 在这个例子中,数组只有4列,但我的原始数组更复杂(7列)。

目前我天真地实施这个:

import pandas as pd
df = pd.DataFrame(array)
grouped1 = df.groupby('column1')
for column1 in grouped1.groups:
    group1 = grouped1.get_group(column1)
    grouped2 = group1.groupby('column2')
    for column2 in grouped2.groups:
        group2 = grouped2.get_group(column2)
        ...

defaultdict方式:

d = defaultdict(lambda x: defaultdict(lambda y: defaultdict ... ))
for row in array:
    d[row[0]][row[1]][row[2]... = row[-1]

但我认为两者都不聪明。

2 个答案:

答案 0 :(得分:4)

我建议这个相当简单的解决方案:

from functools import reduce

data = [['a', 10, 1, 0.1],
        ['a', 10, 2, 0.2],
        ['a', 20, 2, 0.3],
        ['b', 10, 1, 0.4],
        ['b', 20, 2, 0.5]]

result = dict()
for row in data:
    reduce(lambda v, k: v.setdefault(k, {}), row[:-2], result)[row[-2]] = row[-1]

print(result)
{'a': {10: {1: 0.1, 2: 0.2}, 20: {2: 0.3}}, 'b': {10: {1: 0.4}, 20: {2: 0.5}}}

实际的递归解决方案是这样的:

def add_to_group(keys: list, group: dict):
    if len(keys) == 2:
        group[keys[0]] = keys[1]
    else:
        add_to_group(keys[1:], group.setdefault(keys[0], dict()))

result = dict()
for row in data:
    add_to_group(row, result)

print(result)

答案 1 :(得分:1)

简介

这是一个递归解决方案。基本情况是你有一个2元素列表(或元组)的列表,在这种情况下,dict将做我们想要的:

>>> dict([(1, 0.1), (2, 0.2)])
{1: 0.1, 2: 0.2}

对于其他情况,我们将删除第一列并递归,直到我们到达基本案例。

代码:

from itertools import groupby

def rows2dict(rows):
    if len(rows[0]) == 2:
        # e.g. [(1, 0.1), (2, 0.2)] ==> {1: 0.1, 2: 0.2}
        return dict(rows)
    else:
        dict_object = dict()
        for column1, groupped_rows in groupby(rows, lambda x: x[0]):
            rows_without_first_column = [x[1:] for x in groupped_rows]
            dict_object[column1] = rows2dict(rows_without_first_column)
        return dict_object

if __name__ == '__main__':
    rows = [['a', 10, 1, 0.1],
            ['a', 10, 2, 0.2],
            ['a', 20, 2, 0.3],
            ['b', 10, 1, 0.4],
            ['b', 20, 2, 0.5]]
    dict_object = rows2dict(rows)
    print dict_object

输出

{'a': {10: {1: 0.1, 2: 0.2}, 20: {2: 0.3}}, 'b': {10: {1: 0.4}, 20: {2: 0.5}}}

注释

  • 我们使用itertools.groupby生成器来简化基于第一列的类似行的分组
  • 对于每组行,我们删除第一列并递归
  • 此解决方案假定rows变量有2列或更多列。对于具有0或1列的行,结果是不可重现的。