繁体   English   中英

获得有序的独特项目列表的最佳/最pythonic方式

[英]Best / most pythonic way to get an ordered list of unique items

我有一个或多个(不可变的,可散列的)对象的无序序列,可能有重复项,我想得到所有这些对象的排序序列,没有重复。

现在我正在使用一个集合来快速收集所有丢弃重复项的元素,将其转换为列表然后对其进行排序:

result = set()
for s in sequences:
    result = result.union(s)
result = list(result)
result.sort()
return result

它有效,但我不会称之为“漂亮”。 有没有更好的办法?

这应该工作:

sorted(set(itertools.chain.from_iterable(sequences)))

我很喜欢你的代码。 它简单易懂。

我们可以通过链接list()来缩短它一点点:

result = set()
for s in sequences:
    result = result.union(s)
return sorted(result)

我真的不想尝试将其烧掉,但你可以用reduce()来做到这一点:

result = reduce(lambda s, x: s.union(x), sequences, set())
return sorted(result)

就个人而言,我认为这比上面的内容更难理解,但沉浸在函数式编程中的人可能更喜欢它。

编辑:@agf在这个reduce()要比我好多了。 从下面的评论:

return sorted(reduce(set().union, sequences))

我不知道这会起作用。 如果我正确理解它是如何工作的,我们给reduce()一个callable,它实际上是一个set()一个实例上的方法函数(为了讨论起见,将其称为x ,但请注意,我并不是说Python会将名称x与此对象绑定)。 然后reduce()将从sequences的前两个迭代中提供此函数,返回x ,即我们正在使用其方法函数的实例。 然后reduce()将重复调用.union()方法,并要求它从sequences中获取x和下一个iterable的并集。 由于.union()方法可能足够聪明,可以注意到它被要求使用自己的实例获取联合而不需要做任何工作,因此调用x.union(x, some_iterable)速度应该同样快。至于只调用x.union(some_iterable) 最后, reduce()将返回x ,我们有我们想要的集合。

这对我的个人品味来说有点棘手。 我不得不考虑这一点来理解它,而itertools.chain()解决方案立即对我有意义。

编辑:@agf使它不那么棘手:

return sorted(reduce(set.union, sequences, set()))

这样做要简单易懂! 如果我们再次通过名称x调用set()返回的实例(就像上面一样,理解我并不是声称Python会将名称x与此实例绑定); 如果我们使用名称n来引用sequences每个“下一个”值; 然后reduce()将重复调用set.union(x, n) 当然,这与x.union(n)完全相同。 恕我直言,如果你想要一个reduce()解决方案,这是最好的解决方案。

-

如果你想要快速,请问自己:我们有什么方法可以将itertools应用于此吗? 有一个很好的方法:

from itertools import chain
return sorted(set(chain(*sequences)))

*sequences调用的itertools.chain()用于将列表列表“展平”为单个可迭代。 这有点棘手,但只是一点点,这是一个常见的习语。

编辑:正如@Jbernardo在最流行的答案中所写,并且正如@agf在注释中所观察到的, itertools.chain()返回一个具有.from_iterable()方法的对象,文档说它会懒惰地评估迭代。 *表示法强制构建一个列表,如果可迭代是一个长序列,它可能会占用大量内存。 实际上,你可以拥有一个永无止境的生成器,并且使用itertools.chain().from_iterable() ,只要你想运行你的程序就可以从中提取值,而*表示法只会运行记不清。

正如@Jbernardo所写:

sorted(set(itertools.chain.from_iterable(sequences)))

这是最好的答案,我已经对它进行了投票。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM