python - 从对象列表创建动态级别嵌套字典?

标签 python

我正在尝试将对象列表转换为可以通过索引访问的嵌套字典。

以下代码适用于两层嵌套字典。我想扩展它以灵活地处理任意数量的级别。

from collections import namedtuple
import pprint 

Holding = namedtuple('holding', ['portfolio', 'ticker', 'shares'])
lst = [
        Holding('Large Cap', 'TSLA', 100),
        Holding('Large Cap', 'MSFT', 200),
        Holding('Small Cap', 'UTSI', 500)
]

def indexer(lst, indexes):
    """Creates a dynamic nested dictionary based on indexes."""
    result = {}
    for item in lst:
        index0 = getattr(item, indexes[0])
        index1 = getattr(item, indexes[1])
        result.setdefault(index0, {}).setdefault(index1, [])
        result[index0][index1].append(item)
    return result 


d = indexer(lst, ['portfolio', 'ticker'])
pp = pprint.PrettyPrinter()
pp.pprint(d)

输出:

{'Large Cap': {'MSFT': [holding(portfolio='Large Cap', ticker='MSFT', shares=200)],
               'TSLA': [holding(portfolio='Large Cap', ticker='TSLA', shares=100)]},
 'Small Cap': {'UTSI': [holding(portfolio='Small Cap', ticker='UTSI', shares=500)]}}

最佳答案

我见过的实现嵌套字典的最佳方法之一是 Aaron Hall 的 answer问题What is the best way to implement nested dictionaries? .这是一个实现类型的示例,该类型在 Autovivification 中执行名为“Perl”的操作。编程语言。

无论如何,在这里使用一个会很有用,因为这意味着您只需要为树状数据结构的“叶子”调用 setdefault()(它们是 lists,不是子词典)。

因此,这是使用它的问题的答案:

from collections import namedtuple
from functools import reduce
from operator import attrgetter
from pprint import pprint


Holding = namedtuple('Holding', ['portfolio', 'ticker', 'shares'])

lst = [Holding('Large Cap', 'TSLA', 100),
       Holding('Large Cap', 'MSFT', 200),
       Holding('Small Cap', 'UTSI', 500),]

def indexer(lst, indexes):
    """ Creates a dynamic nested dictionary based on indexes. """

    class Vividict(dict):
        """ dict subclass which dynamically creates sub-dictionaries when
            they're first referenced (and don't exist).
            See https://stackoverflow.com/a/19829714/355230
        """
        def __missing__(self, key):
            value = self[key] = type(self)()
            return value

    result = Vividict()
    index_getters = attrgetter(*indexes)
    for item in lst:
        *indices, leaf = index_getters(item)  # Leaves are lists, not dicts.
        target = reduce(lambda x, y: x[y], indices, result)
        target.setdefault(leaf, []).append(item)

    return result

d = indexer(lst, ['portfolio', 'ticker'])
pprint(d)
print()
d = indexer(lst, ['portfolio', 'ticker', 'shares'])
pprint(d)

输出:

{'Large Cap': {'MSFT': [Holding(portfolio='Large Cap', ticker='MSFT', shares=200)],
               'TSLA': [Holding(portfolio='Large Cap', ticker='TSLA', shares=100)]},
 'Small Cap': {'UTSI': [Holding(portfolio='Small Cap', ticker='UTSI', shares=500)]}}

{'Large Cap': {'MSFT': {200: [Holding(portfolio='Large Cap', ticker='MSFT', shares=200)]},
               'TSLA': {100: [Holding(portfolio='Large Cap', ticker='TSLA', shares=100)]}},
 'Small Cap': {'UTSI': {500: [Holding(portfolio='Small Cap', ticker='UTSI', shares=500)]}}}

关于python - 从对象列表创建动态级别嵌套字典?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47983728/

相关文章:

Python lxml 对象化 : Strange behaviour when changing an elements value

Python WSGI + Flask render_template - 500 内部服务器错误?

python - 使用 Python 和 Beautiful Soup 从 .html 文件中提取文本,删除 HTML,然后写入文本文件

python - 如何使用pyquery python触发事件

python - 一个 Django 模型字段作为字符串数组,另一个字段作为下拉列表,其中包含第一个字段的选择?

python - Mongodb 组平均数组

python - 如何将插入符号移动到 PyCharm 中一行的开头或中间

python - 有没有一种简单的方法来获取所有常见的模块扩展?

python - Weka GUI 和 Weka 通过 python api 的结果不同

python - Python Tornado 中的异常处理