Python 展平列表中的词典(2层深)
我试着让我的大脑围绕着这个,但它不够灵活 在我的Python脚本中,我有一个列表字典字典。(事实上,它变得更深了一点,但这个问题没有涉及到这个层次。)我想把所有这些放在一个长长的列表中,扔掉所有的字典键 所以我想改变Python 展平列表中的词典(2层深),python,data-structures,mapreduce,dictionary,Python,Data Structures,Mapreduce,Dictionary,我试着让我的大脑围绕着这个,但它不够灵活 在我的Python脚本中,我有一个列表字典字典。(事实上,它变得更深了一点,但这个问题没有涉及到这个层次。)我想把所有这些放在一个长长的列表中,扔掉所有的字典键 所以我想改变 {1: {'a': [1, 2, 3], 'b': [0]}, 2: {'c': [4, 5, 1], 'd': [3, 8]}} 到 我可能会设置一个MapReduce来迭代外部字典的项,从每个子字典构建一个子列表,然后将所有子列表连接在一起 但这对于大型数据集来说似乎效率低
{1: {'a': [1, 2, 3], 'b': [0]},
2: {'c': [4, 5, 1], 'd': [3, 8]}}
到
我可能会设置一个MapReduce来迭代外部字典的项,从每个子字典构建一个子列表,然后将所有子列表连接在一起
但这对于大型数据集来说似乎效率低下,因为中间数据结构(子列表)将被丢弃。有没有一种方法可以一次性完成
除此之外,我很乐意接受一个两级实现,它可以工作。。。我的地图生锈了
更新:
对于那些感兴趣的人,下面是我最终使用的代码
注意,尽管我在上面要求输出一个列表,但我真正需要的是一个排序列表;i、 e.展平的输出可以是任何可以排序的iterable
def genSessions(d):
"""Given the ipDict, return an iterator that provides all the sessions,
one by one, converted to tuples."""
for uaDict in d.itervalues():
for sessions in uaDict.itervalues():
for session in sessions:
yield tuple(session)
再次感谢所有帮助过我的人
[更新:由于@intuited,将
nthGetter()
替换为operator.itemgetter()
。我希望您认识到,您在dict中看到的任何顺序都是偶然的——它的存在只是因为当在屏幕上显示时,必须选择一些顺序,但绝对没有保证
各子列表之间的排序问题得到链接
[x for d in thedict.itervalues()
for alist in d.itervalues()
for x in alist]
在没有任何低效或中间列表的情况下执行您想要的操作。递归函数可以工作:
def flat(d, out=[]):
for val in d.values():
if isinstance(val, dict):
flat(d, out)
else:
out+= val
如果您尝试使用:
>>> d = {1: {'a': [1, 2, 3], 'b': [0]}, 2: {'c': [4, 5, 6], 'd': [3, 8]}}
>>> out = []
>>> flat(d, out)
>>> print out
[1, 2, 3, 0, 4, 5, 6, 3, 8]
请注意,字典没有顺序,因此列表是随机顺序的
您还可以返回(在循环结束时),并且不使用列表参数调用函数
def flat(d, out=[]):
for val in d.values():
if isinstance(val, dict):
flat(d, out)
else:
out+= val
return out
称为:
my_list = flat(d)
编辑:重新阅读原始问题和修改后的答案,假设所有非词典都是要展平的列表
如果您不确定字典到底有多远,您可能希望使用递归函数@Arrieta已经有了一个递归构建非字典值列表的函数
这是一个生成器,在字典树中生成连续的非字典值:
def flatten(d):
"""Recursively flatten dictionary values in `d`.
>>> hat = {'cat': ['images/cat-in-the-hat.png'],
... 'fish': {'colours': {'red': [0xFF0000], 'blue': [0x0000FF]},
... 'numbers': {'one': [1], 'two': [2]}},
... 'food': {'eggs': {'green': [0x00FF00]},
... 'ham': ['lean', 'medium', 'fat']}}
>>> set_of_values = set(flatten(hat))
>>> sorted(set_of_values)
[1, 2, 255, 65280, 16711680, 'fat', 'images/cat-in-the-hat.png', 'lean', 'medium']
"""
try:
for v in d.itervalues():
for nested_v in flatten(v):
yield nested_v
except AttributeError:
for list_v in d:
yield list_v
doctest将生成的迭代器传递给set
函数。这可能是你想要的,因为正如马尔泰利先生所指出的,字典的值没有内在的顺序,因此没有理由跟踪它们被发现的顺序
您可能希望跟踪每个值的出现次数;如果将迭代器传递给集
,则此信息将丢失。如果您想跟踪它,只需将flatte(hat)
的结果传递给其他函数,而不是set
。在Python2.7下,另一个函数可以是collections.Counter
。为了与进化程度较低的python兼容,您可以编写自己的函数,或者(在一定程度上降低了效率)将sorted
与itertools相结合。groupby
谢谢。这正是我想要的。。。简洁高效。我计划在以后对扁平列表进行排序。我的示例输出并不是为了暗示一个已定义的顺序,但您检查一下很好。@Lipis:有什么特别的原因吗?这是一个很好的答案,但我在评论中解释了为什么我接受了intuited的答案。@LarsH aha。。我没怎么注意。。偶然发现这个问题,我以为它被遗忘了或是什么的:)而且我是亚历克斯的粉丝。。不过别介意我现在读了评论,谢谢你提供了信息丰富的答案。我使用的数据结构是规则的,但是为了通用性,我很高兴学习递归方法。对于set(),元素似乎必须是可散列的,这在我的例子中是不正确的:正如我在原始问题中提到的,元素本身就是列表。不过,我可能会将它们转换为元组,因为它们不再需要是可变的。虽然我已经接受了Alex的优秀答案,但我会改为接受这个答案。希望这不是失礼。原因:1)这提供了一个迭代器而不是列表,传递给sorted()可能比传递给将被丢弃的显式中间列表更有效(尽管我要求将列表作为输出)。2) 你投入了大量的时间和解释;我学到了更多。3) 分数对你来说比对他更重要。:-)@拉尔斯:啊,你是说“它变得更深一点”的评论。是的,如果将dict中dict中的列表转换为元组,则可以将它们添加到集合中。类似于set(tuple(list)for list_uuu,in flatte(hat))
的方法将是最简单的方法。尽管您希望这样做的事实表明,可能有理由将它们保留为列表,或者从一开始就使用元组。再说一次,如果你真的想在这个点的可变存在中创建一个“快照”,那么这样做是有意义的。。。我偶尔会有不同的元素,它们的值相等,我希望它们是不同的,但它们的数量不够(它们的相等性也不重要),因此值得对每个元素进行计数。在我构建元素时,元素需要是可变的,但它们不需要再超过这一点。如果您感兴趣,我发布了我最终使用的代码。再次感谢你的帮助。谢谢你的回答。我从中学到了一些好东西!比如使用+=(aka.append())将累加列表连接在一起,这样就不会构建临时中间列表。您可以从这个示例中学到更多:关于无限递归和关于函数argumentsCool使用默认值的错误方法,可以这么说,很高兴您对它进行了排序。一对夫妇
my_list = flat(d)
def flatten(d):
"""Recursively flatten dictionary values in `d`.
>>> hat = {'cat': ['images/cat-in-the-hat.png'],
... 'fish': {'colours': {'red': [0xFF0000], 'blue': [0x0000FF]},
... 'numbers': {'one': [1], 'two': [2]}},
... 'food': {'eggs': {'green': [0x00FF00]},
... 'ham': ['lean', 'medium', 'fat']}}
>>> set_of_values = set(flatten(hat))
>>> sorted(set_of_values)
[1, 2, 255, 65280, 16711680, 'fat', 'images/cat-in-the-hat.png', 'lean', 'medium']
"""
try:
for v in d.itervalues():
for nested_v in flatten(v):
yield nested_v
except AttributeError:
for list_v in d:
yield list_v