【问题标题】:Is there an efficient way to filter the maximum numbers in a list有没有一种有效的方法来过滤列表中的最大数字
【发布时间】:2021-07-08 17:36:06
【问题描述】:

我只是想知道是否有更好的方法来查找列表中的所有最大数字。

例如,我有一个字典列表。它有一个键(“信息”)和对应的字典值,如下所示。我想从该列表中找到最大数量s(“计数”)。一旦找到最大数量,就必须确定该元素的相应“代码”。

我可以按如下方式进行,但是对于一个非常大的列表,执行时间会很长。

codes = [{"code": 1, "info": {"status": "running", "count": 4}},
         {"code": 2, "info": {"status": "running", "count": 1}},
         {"code": 3, "info": {"status": "running", "count": 2}},
         {"code": 4, "info": {"status": "running", "count": 4}},
         {"code": 5, "info": {"status": "running", "count": 4}}
         ]
count_max = 0
filtered_codes = []
for i in range(len(codes)):
    if codes[i]['info']['count'] == count_max:
        filtered_codes.append(codes[i]['code'])
    if codes[i]['info']['count'] > count_max:
        filtered_codes.clear()
        filtered_codes.append(codes[i]['code'])
        count_max = codes[i]['info']['count']
print(filtered_codes)

输出: [1, 4, 5] #1,4,5 是字典的代码,count == 4(所有计数中的最大值)

那么,有没有更好的方法来做到这一点?可能正在使用过滤器,lambda,max?

编辑:有人发布了以下代码作为答案,后来被删除了

max_count = max(info["info"]["count"] for info in codes)
filtered_codes = [val["code"] for val in filter(lambda x: x["info"]["count"] == max_count, codes)]

所以我在长度 1000000

的列表上运行了两个代码

我发布的第一个方法是:1.4539954662322998s

采取第二种方法:0.4440000057220459s

那么第二种方法是最好的解决方案吗?

【问题讨论】:

  • 您的方法已经是O(N)。如果使用filter()lambdas 和max() 执行此操作,性能不会有显着提高。为了使它更pythonic,您可以将for i in range(len(codes)) 更改为for i, elem in enumerate(codes),然后使用elem 而不是codes[i],但是试图将所有内容都塞进一行会适得其反,因为它不会导致很大的加速但会产生巨大的影响代码的可读性。
  • @PranavHosangadi 我已经更新了这个问题,请您提供一些关于它的见解

标签: python-3.x


【解决方案1】:

您的代码是执行此操作的最渐近有效的方法。您的代码也很好,因为它可以在流上运行——使用max 然后filter 需要多次通过。使用这些内置函数的好处是可读性。

如果您真的需要性能,您可能希望使用 numpy 之类的库或用 C 编写代码。

更新的问题: 是的,我的意思是它们都是渐近线性时间。在现实世界中哪个更快取决于您看到的输入类型,以及缓存和解释器的怪癖。例如,对于 count = [1,1,1,1,1,1,...,1,2] 这样的特定数据集,第二个肯定会更快。第一个示例是通过慢速网络从远程服务流式传输 10TiB 随机输入列表的速度更快。要进行真正的比较,您需要定义要测试的数据集空间。

对于您生成的输入数据,解决方案 2 是“最佳”吗?好吧,我的意思是有更多的优化方法——例如,一旦确定了最大值,您就可以启动线程并划分输入列表以进行过滤。取决于你想走多远。

我个人更喜欢编写(和阅读)第二个示例。因为它有效且易于理解。更进一步,在理解中使用 if 而不是 filter 可能更惯用,即

max_count = max(info["info"]["count"] for info in codes)
filtered_codes = [val["code"] for val in codes if val["info"]["count"] == max_count]

就像我之前说的,如果你真的关心大数据的超高性能,你显然不想使用纯 Python。

【讨论】:

  • 另外,您的代码需要线性额外空间。尽管对于这个问题,对于额外空间来说,这不是最好的,但对于总空间来说,这是最好的。在知道要返回哪些元素之前,您需要查看整个列表。换句话说,切换到链表结构来存储候选元素没有任何优势。
  • 我已经更新了这个问题,请您提供一些关于它的见解
  • 完成,我知道这不是 codereview.stackexchange 但总是很乐意分享我对代码的看法
猜你喜欢
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多