从列表中删除重复项并以相反顺序排序的最佳/最pythonic方法

时间:2018-10-19 04:02:33

标签: python list sorting set

我正在尝试使用list(下面的orig_list)并返回list(下面的new_list),

  • 不包含重复项(即仅包含唯一元素)
  • 以相反的顺序排序

到目前为止,这里是我所拥有的,似乎……我要说“很奇怪”,尽管我敢肯定有一种更好的说法。我大部分时间都因为两次使用list()而显得很简单,然后才开始怀疑这种方法的效率。

new_list = list(reversed(sorted(list(set(orig_list)))))

问题1 (SO风格的问题):

以下命题正确吗?

  1. 获取list的唯一元素没有比将list转换为set并返回的更有效的方法。
  2. sets are unordered in Python起,必须(1)在删除重复项之前转换为集合,因为否则会丢失排序,并且(2)在排序之前必须转换回列表。 li>
  3. 在程序上,使用list(reversed())等效于使用list.sort(reversed = True)。

问题2 (奖励):

是否有任何方法可以在更少的操作系统中获得相同的结果,或者使用更少的冗长方法?如果是这样,什么是/是一些示例?

2 个答案:

答案 0 :(得分:3)

sorted(set(orig_list), reverse=True)

代码中最短的代码,效率更高,结果相同。

取决于大小,如user2864740在注释中建议的那样,在线性时间中先排序然后进行重复数据删除可能更快,也可能不会更快。 (该方法的最大缺点是,它完全是用Python编写的,而以上代码行大部分是在本机代码中执行的。)

您的问题:

  • 您不需要从set转换为list再返回。 sorted接受任何可迭代项,因此set合格,并吐出一个列表,因此不需要进行转换后的操作。

  • reversed(sorted(x)) 等效于sorted(x, reverse=True)。您得到相同的结果,但速度较慢-sort的速度相同,无论正向还是反向,因此reversed添加了一个额外的操作,如果您从一开始就按正确的顺序进行排序,则不需要此操作。 / p>

答案 1 :(得分:2)

您在这里有一些轻度浪费的步骤,但是您的主张在很大程度上是正确的。要做的唯一真正的改进就是摆脱所有不必要的临时list

new_list = sorted(set(orig_list), reverse=True)

sorted已经将其输入转换为list(因此在传递给list之前无需sorted进行修饰),您可以让它直接产生输出{ {1}}进行反向排序(因此,无需产生list即可仅对其进行反向复制)。

可以想象的,大O时间的唯一改进是如果您知道已经对数据进行了排序,在这种情况下,您可以避免list排序,并在不丢失现有排序顺序的情况下进行唯一化由using itertools.groupby

O(n log n)

如果 new_list = [key for key, grp in itertools.groupby(orig_list)] 按正序排序,则可以通过将orig_list更改为itertools.groupby(orig_list)来使结果几乎免费地反转。

itertools.groupby(reversed(orig_list))解决方案对于最初未排序的输入实际上并不实用,因为如果重复项在远程情况下甚至很常见,那么通过uniquification作为groupby步骤将其删除几乎是值得的,因为它减少了O(n)在更昂贵的n排序步骤中。 O(n log n)也是一个相对较慢的工具;对于每组使用一堆临时迭代器,值的内部缓存等实现的性质,实际上比通过groupby进行O(n)唯一化的O(n)慢,其主要优点是流传输方面(使其能够扩展到从磁盘或网络流传输的数据集,并且可以长期存储而无需存储任何东西,set必须将所有内容都拉到内存中。)

使用set + sorted的另一个原因是,如果您的数据不可散列,但具有可比性;在这种情况下,groupby不是一个选项,因此唯一的选择是排序和分组。