【问题标题】:What is the fastest way to split a list into multiple sublists based on several conditions?根据多个条件将列表拆分为多个子列表的最快方法是什么?
【发布时间】:2022-01-19 09:53:36
【问题描述】:

根据条件将列表拆分为多个子列表的最快方法是什么?每个条件代表一个单独的子列表。

一种将listOfObjects 拆分为子列表的方法(三个子列表用于演示,但也可以更多):

listOfObjects = [.......]
l1, l2, l3 = [], [], []
for l in listOfObjects:
    if l.someAttribute == "l1":
        l1.append(l)
    elif l.someAttribute == "l2":
        l2.append(l)
    else:
        l3.append(l)

这种方式看起来一点也不像pythonic,而且还需要相当长的时间。是否有更快的方法,例如使用map?

有一个类似的问题,但只有一个条件,即两个结果列表:How to split a list based on a condition?

【问题讨论】:

  • 您想将l1l2 以外的类别放在一个列表中吗?还是每个类别都会进入一个单独的列表?
  • 每个类别一个单独的列表
  • 请在问题本身中提及这一点。这对未来的读者会有帮助。评论可能会被删除。

标签: python python-3.x list performance


【解决方案1】:

您可以在此处collections.defaultdict 进行映射。

from collections import defaultdict

d = defaultdict(list)

for l in listOfObjects:
    d[l.someAttribute].append(l)

out = d.values() 
l1 , l2, l3 = d['l1'], d['l2'], d['l3']

d 的格式为。

{ 
  attr1 : [...],
  attr2 : [...],
  ...
  attrn : [...]
}

【讨论】:

  • 我非常喜欢您的回答,因为它是一个可读且可扩展的解决方案。现在到我问题的第二部分:你能提供一些速度测试吗?
  • @MichaelSzczesny 我以为这只是为了演示。我认为 OP 想根据属性值拆分(分组)它们。我的错。
  • @MichaelSzczesny 如果 OP 也想要默认类别,我会删除我的答案。
  • @MichaelSzczesny 在 OP 在comments 中澄清他们想要“每个类别有一个单独的列表” 之后,我没有删除我的答案。
【解决方案2】:

类似问题的答案令人惊叹。我没有考虑过拆分...无论如何,您可以执行类似的操作,但可读性会降低:

for l in listOfObjects:
    (l3, l2, l1)[(l.someAttribute == "l1")*2 or l.someAttribute == "l2"].append(l)

这适用于任何布尔条件。 or 返回第一个真值(或 False)。 True==1,所以我们为希望等于 2 的索引添加 *2。

但正如我所说,它不是真正可读的。而且不可扩展。

至于速度:or 是短路的,返回第一个真值,所以条件检查应该和你的方法类似。您可能希望将查找元组定义在循环之外。


而且使用 dict 更具可读性,因为您的条件基于相等(注意:您想要的属性也必须是可散列的)

lookup = {"l1": l1, "l2": l2}
for l in listOfObjects:
    lookup.get(l.someAttribute, l3).append(l)

dict.get 将默认值设为第二 - 所以它非常适合我们的 else 包罗万象。

在速度方面:字典查找将只有一次检查,而不是 or 链的条件链 ifs

【讨论】:

  • OP 提到了“三个子列表用于演示,但更多是可能的使用上述方法很难扩大规模。
  • 这就是为什么那里还有 dict 方法。 ;)
  • 你会如何扩展你的字典版本?除非你事先知道所有的属性值?
  • OP 演示了 ifs 的相等性,表明他们知道某个地方的值。+ 考虑到他们使用else,我假设他们只想知道其中的一些,然后对其余部分进行全面了解。如果他们不想要包罗万象,那么是的,defaultdict 更好。 |但是,即使我们得出结论认为这不是这个案例的最佳解决方案,我也会把我的答案留在那里,以防有类似问题的人来到这里。 :)
  • 知道了。 :) 问题尚不清楚 OP 是否想要“默认”类别。我希望他们能澄清这个问题。
猜你喜欢
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2022-12-22
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 1970-01-01
  • 2023-01-10
相关资源
最近更新 更多