【问题标题】:List splitting by predicate按谓词拆分列表
【发布时间】:2012-08-15 18:31:21
【问题描述】:

有没有更简洁的方法通过谓词将一个列表分成两个列表?

errors, okays = [], []
for r in results:
    if success_condition(r):
        okays.append(r)
    else:
        errors.append(r)

我知道这可以使用reduce 变成一个丑陋的单线;这不是我要找的。​​p>

更新:每个元素只计算一次 success_condition 是可取的。

【问题讨论】:

  • 你的代码没问题。所有提出的解决方案都是循环并应用过滤功能两次。
  • @PaoloMoretti:我同意你的第一句话,但你的第二句话是错误的——参见 dbaupp 的。
  • @PaoloMoretti,以及 dfb 的第二个建议。
  • 我也同意@PaoloMoretti 的第一句话,这是代码很好。这些解决方案没有你的优势

标签: python


【解决方案1】:

也许

for r in results:
    (okays if success_condition(r) else errors).append(r)

但这看起来/感觉不是很 Pythonic。


不直接相关,但如果追求效率,缓存方法查找会更好:

okays_append = okays.append
errors_append = errors.append

for r in results:
    (okays_append if success_condition(r) else errors_append)(r)

这更不像 Pythonic。

【讨论】:

    【解决方案2】:

    怎么样

    errors = [ r for r in results if not success_condition(r)]
    okays = [ r for r in results if success_condition(r)]
    

    或者

    bools = [ success_condition(r) for r in results ] 
    

    如果 success_condition 是一个代价高昂的调用,然后替换上面(通过 zipenumerate)..

    【讨论】:

    • 但是为了得到好的,你需要再次过滤——有效地检查每个元素两次(这可能很昂贵)。
    • 是的,这是真的,但他要求的是简洁,而不是效率
    • @dfb 我删除了它,因为它实际上并不简洁。
    • 我认为当你将boolszip 结合起来时,它不会再简洁了
    • @gnibbler - 真的吗?它变成了okays = [ r[0] for r in zip(results,bools) if r[1]]。不是更糟......或者你指的是它是 3 行而不是 2 行?
    【解决方案3】:
    errors, okays = [], []
    for r in results:
        (errors, okays)[success_condition(r)].append(r)
    

    【讨论】:

    • 太酷了 :) 我想知道它是否通过了我们的代码审查,但无论如何。
    【解决方案4】:

    使用带有副作用的生成器表达式或列表推导。(只是为了使其看起来简洁):

    >>> errors, okays = [], []
    >>> [okays.append(r) if success_condition(r) else errors.append(r)  for r in results]
    

    带有生成器表达式:

    >>> errors, okays = [], []
    >>> list(okays.append(r) if success_condition(r) else errors.append(r)  for r in results)
    

    【讨论】:

    • 这真的行不通。生成器表达式中的任何内容尚未执行。您需要使用列表推导(或以某种方式遍历生成器表达式,例如[None for _ in <genexpr> if False])。
    • @dbaupp 我想list(<gen expr>) 就可以了。
    • 当然(相当于列表推导)。但我的另一个建议避免为列表分配大块内存,然后立即丢弃。
    • (虽然刚才做了一些快速测试表明我的诡计比普通的list(..)调用慢,哈哈!)
    • any(<get expr>) 更好,因为 list.append 总是返回 False 它将贯穿整个事情
    【解决方案5】:

    filter 函数呢?

    okays = filter(success_condition, results)
    errors = filter(lambda (x): not success_condition(x), results)
    

    【讨论】:

    • 它应用谓词两次,这是不可取的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多