基于谓词在python中分区数组

时间:2012-08-29 23:59:41

标签: python arrays

  

可能重复:
  python equivalent of filter() getting two output lists (i.e. partition of a list)

我在python中有一个数组,想要将它分成两个数组,一个是元素与谓词匹配,另一个是元素不匹配。

是否有比以下更简单的方式(或更多Pythonic):

>>> def partition(a, pred):
...   ain = []
...   aout = []
...   for x in a:
...     if pred(x):
...       ain.append(x)
...     else:
...       aout.append(x)
...   return (ain, aout)
...
>>> partition(range(1,10), lambda x: x%3 == 1)
([1, 4, 7], [2, 3, 5, 6, 8, 9])

6 个答案:

答案 0 :(得分:2)

您目前拥有的内容比其他任何方式都更简单,更有效。

以下是一些关于如何重写此代码的潜在选项,以及为什么我认为您的版本更好:

  • 使用集合 - 订单不会保留,仅适用于可投放内容
  • 使用tee / filter / ifilterfalse - 取决于您使用结果的方式,最终使用更多内存,并重复两次
  • 使用numpy - 不适用于通用迭代,需要迭代两次以获得两种条件的结果

答案 1 :(得分:1)

def partition(a,pred):
  f1 = set(filter(pred,a))
  f2 = set(a) - f1
  return f1,f2

更pythonic ......但不确定它是否更快

[编辑]我不认为订单被保留......(并且在两条评论中都有更好的答案和链接)

答案 2 :(得分:1)

另一种说同样的话。请注意,两个列表的顺序相反。

def partition(a, pred):
    aout_ain = [], []
    for x in a:
        aout_ain[pred(x)].append(x)
    return aout_ain

如果您需要首先使用“ins”,则只需添加not

即可
def partition(a, pred):
    ain_aout = [], []
    for x in a:
        ain_aout[not pred(x)].append(x)
    return ain_aout

答案 3 :(得分:0)

您可以访问NumPy吗? Numpy的索引容量使得根据某些条件选择numpy ndarray的条目非常容易。例如

>>> import numpy as np
>>> a = np.arange(1, 10)
>>> condition = (a % 3 == 1)
>>> a[condition]
array([1, 4, 7])
>>> a[~condition]
array([2, 3, 5, 6, 8, 9])

NumPy对大型阵列特别有效。对于小的,不是那么多。

答案 4 :(得分:0)

#from http://docs.python.org/dev/library/itertools.html#itertools-recipes

def partition(pred, iterable):
    'Use a predicate to partition entries into false entries and true entries'
    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
    t1, t2 = tee(iterable)
    return ifilterfalse(pred, t1), filter(pred, t2)

答案 5 :(得分:-1)

不是Pythonic,但有点功能:

>>> partition = lambda xs, p: reduce(lambda (a, b), c: p(c) and (a + [c], b) or (a, b + [c]), xs, ([], []))
>>> print partition(range(1, 10), lambda x: x % 3 == 1)
([1, 4, 7], [2, 3, 5, 6, 8, 9])