【发布时间】:2020-02-27 08:29:26
【问题描述】:
我正在努力解决这个问题,但它不够灵活。
在我的 Python 脚本中,我有一个列表字典。 (实际上它变得更深了,但这个问题不涉及这个级别。)我想把所有这些都压缩成一个长列表,扔掉所有的字典键。
所以我想变身
{1: {'a': [1, 2, 3], 'b': [0]},
2: {'c': [4, 5, 1], 'd': [3, 8]}}
到
[1, 2, 3, 0, 4, 5, 1, 3, 8]
我可能会设置一个 map-reduce 来迭代外部字典的项目,以从每个子字典构建一个子列表,然后将所有子列表连接在一起。
但这对于大型数据集来说似乎效率低下,因为中间数据结构(子列表)会被丢弃。有没有办法一次性完成?
除此之外,我很乐意接受一个有效的两级实现......我的 map-reduce 生锈了!
更新: 对于那些感兴趣的人,下面是我最终使用的代码。
请注意,尽管我在上面要求一个列表作为输出,但我真正需要的是一个排序列表;即展平的输出可以是任何可以排序的迭代。
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)
...
# Flatten dict of dicts of lists of sessions into a list of sessions.
# Sort that list by start time
sessionsByStartTime = sorted(genSessions(ipDict), key=operator.itemgetter(0))
# Then make another copy sorted by end time.
sessionsByEndTime = sorted(sessionsByStartTime, key=operator.itemgetter(1))
再次感谢所有提供帮助的人。
[更新:将nthGetter() 替换为operator.itemgetter(),感谢@intuited。]
【问题讨论】:
-
酷,很高兴你把它整理好了,可以这么说。您可能知道或可能不知道的几件事:1)采用 Martelli 先生的回答并将括号(即
[、])更改为括号将使其成为执行相同操作的“生成器表达式”作为你的genSessions函数,可以说可读性有点差。 -
2) 标准库函数
operator.itemgetter与您的nthGetter做同样的事情。该模块中的函数在 C 中实现并针对速度进行了调整,因此如果这是一个瓶颈,则使用该函数可以为您提供加速。它还可以让你通过使用一个常用的习惯来减少代码的大小,这总是很好的。 -
@intuited - 感谢您的两个提示。我不知道制作匿名生成器 (1) - 我会这样做,尽管正如你所说,它可能更具可读性。 (2) 我以为我曾在这样的操作员身上看到过,但是当我看的时候却找不到。我一定会使用 itemgetter。
-
@ninjagecko:我回滚了你的更改。您的编者注(“由于这不使用递归或外积原语,它只能在深度完全等于 2 的嵌套列表上工作”),虽然是真的,但属于评论。如问题中所述,我将代码设计为在深度为 2 的嵌套结构上工作。我恢复了标题,因为您更改的标题描述了接受的解决方案而不是问题;而人们通常从问题开始。
-
我很抱歉。我已经把你刚才说的“(2层深)”的标题说清楚了,让更多的人不糊涂。由于标题相似,另一个问题被标记为重复。
标签: python data-structures mapreduce dictionary