1

可能重复:
python 等效于 filter() 获取两个输出列表(即列表的分区)

我在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])
4

6 回答 6

2

您目前拥有的方法比任何其他方法都更简单、更有效。

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

  • 使用集合 -不保留顺序,仅适用于可散列的内容
  • 使用 tee/filter/ifilterfalse -取决于你如何使用结果,你最终会使用更多的内存,并迭代两次
  • 使用 numpy -不适用于通用可迭代对象,需要迭代两次以获得两种条件的结果
于 2012-08-30T00:13:20.640 回答
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
于 2012-08-30T00:42:23.923 回答
1
def partition(a,pred):
  f1 = set(filter(pred,a))
  f2 = set(a) - f1
  return f1,f2

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

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

于 2012-08-30T00:05:38.133 回答
0

你可以访问 NumPy 吗?ndarrayNumpy 的索引能力使得根据某些条件选择 numpy 的条目变得非常容易。例如

>>> 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 对于大型数组特别有效。对于小的,没有那么多。

于 2012-08-30T00:06:32.770 回答
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)
于 2012-08-30T00:07:43.250 回答
-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])
于 2012-08-30T00:23:13.380 回答