【问题标题】:partitioning arrays in python based on a predicate [duplicate]基于谓词在python中分区数组[重复]
【发布时间】:2012-08-29 23:59:41
【问题描述】:

可能重复:
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])

【问题讨论】:

  • 呵呵,发帖前我试过搜索,没找到——谢谢!

标签: python arrays


【解决方案1】:

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

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

  • 使用集合 - 不保留顺序,仅适用于可散列的内容
  • 使用 tee/filter/ifilterfalse - 根据您使用结果的方式,您最终会使用更多内存并迭代两次
  • 使用 numpy - 不适用于泛型可迭代对象,需要迭代两次以获得两种条件的结果

【讨论】:

    【解决方案2】:
    def partition(a,pred):
      f1 = set(filter(pred,a))
      f2 = set(a) - f1
      return f1,f2
    

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

    [编辑],我不认为订单被保留......(在两个带有链接的 cmets 中都有更好的答案)

    【讨论】:

      【解决方案3】:

      只是说同一件事的另一种方式。请注意,这两个列表的顺序是相反的。

      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
      

      【讨论】:

        【解决方案4】:

        您可以访问 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 对于大型数组尤其有效。对于小的,没有那么多。

        【讨论】:

          【解决方案5】:
          #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)
          

          【讨论】:

          【解决方案6】:

          不是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])
          

          【讨论】:

            猜你喜欢
            • 2021-09-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多