Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 展平列表中的词典(2层深)_Python_Data Structures_Mapreduce_Dictionary - Fatal编程技术网

Python 展平列表中的词典(2层深)

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来迭代外部字典的项,从每个子字典构建一个子列表,然后将所有子列表连接在一起 但这对于大型数据集来说似乎效率低

我试着让我的大脑围绕着这个,但它不够灵活

在我的Python脚本中,我有一个列表字典字典。(事实上,它变得更深了一点,但这个问题没有涉及到这个层次。)我想把所有这些放在一个长长的列表中,扔掉所有的字典键

所以我想改变

{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