这是垂直切片字典列表以获取唯一值的最有效方法吗?

时间:2013-09-24 00:54:10

标签: python python-2.7

我有一个字典列表,我正在寻找其中一个键的唯一值列表。

这就是我想出来的,但不禁想知道它的效率,时间和/或记忆是否明智:

list(set([d['key'] for d in my_list]))

有更好的方法吗?

1 个答案:

答案 0 :(得分:6)

此:

list(set([d['key'] for d in my_list]))

...构造所有值的列表,然后构造一组唯一的值,然后从集合中构造一个列表。

假设你有10000件商品,其中1000件是独一无二的。您已将最终存储量从10000个项目减少到1000个,这很好 - 但您已将峰值存储量从10000增加到11000(因为显然必须有整个列表和几乎整个集合同时存在于内存中的时间)。

有两种非常简单的方法可以避免这种情况。

首先(只要你有Python 2.4或更高版本)使用生成器表达式而不是列表推导。在大多数情况下,包括这个,只需要删除方括号或将它们变成括号:

list(set(d['key'] for d in my_list))

或者,更简单地说(使用Python 2.7或更高版本),只需使用集合理解而不是列表理解来直接构造集合:

list({d['key'] for d in my_list})

如果您遇到Python 2.3或更早版本,则必须编写显式循环。使用2.2或更早版本时,没有任何集合,因此您必须使用dict将其伪装成None或类似的伪造。


超越太空,时间怎么样?好吧,显然你必须遍历10000个字典的整个列表,并为每个字典做一个O(1)dict.get

原始版本为每个步骤执行list.append(实际上内部等效内容稍微快一些),然后set转换遍历具有{{set.add相同大小的列表1}}对于每一个,然后list转换是一个较小的集合的遍历,每个集合list.append。所以,它是O(N),它在算法上显然是最优的,并且只是通过一个小的乘数而不仅仅是迭代列表并且什么也不做。

设置版本跳过list.append,只迭代一次而不是两次。所以,它也是O(N),但乘数更小。内存管理的节省(如果N足够重要)也可能有所帮助。