【问题标题】:How to filter lists in a list?如何过滤列表中的列表?
【发布时间】:2014-09-27 06:18:03
【问题描述】:

我有,例如,listy = [[1,-1,2], [3,-2,-4]]

我想过滤,只得到正元素 [[1,2], [3]]

使用循环和过滤器(lambda x: x > 0, listy)很容易做到这一点,但我想避免循环。

【问题讨论】:

  • 我不相信没有某种循环可以解决这个问题。如果有人知道不同,加 1 ^^
  • @T.Woody:取决于您将什么视为循环。递归是循环吗?一个循环展开成一堆重复的代码是一个循环吗?我认为答案是“就任何重要的事情而言”,但其他人可能不同意;看我的回答。

标签: python list filter


【解决方案1】:

列表推导可以嵌套:

In [2]: [ [i for i in x if i>0] for x in listy ]
Out[2]: [[1, 2], [3]]

关于filter和列表推导之间的选择,Guido van Rossum, the BDFL, wrote列表推导更清晰更快捷;

filter(P, S) 几乎总是写成 [x for x in S if P(x)],这有一个巨大的优势,最常见的用法 涉及比较的谓词,例如x==42,并定义一个 lambda 只需要读者付出更多的努力(加上 lambda 比列表理解要慢)。

高级主题:处理大型数据集

如果listy 很大并且您的应用程序允许,您可能希望使用生成器来代替列表:

g = ( (i for i in x if i>0) for x in listy )

【讨论】:

    【解决方案2】:

    您的问题本质上需要一个循环。您想为listy 的每个成员做点什么,for 甚至是英文的。

    但是,您可以将循环包装在一个理解中,或者调用map 等。例如:

    listy = map(lambda sublist: filter(lambda x: x>0, sublist), listy)
    listy = [[x for x in sublist if x>0] for sublist in listy]
    

    (或者,当然,上面的其他两种组合,对filter 的理解,或对理解的map。)

    您也可以懒惰地进行循环,因此与其浪费时间创建过滤列表,您只需创建将按需生成正值的迭代器:

    itery = itertools.imap(lambda sublist: itertools.ifilter(lambda x: x>0, sublist), listy)
    itery = ((x for x in sublist if x>0) for sublist in listy)
    

    但这只是意味着循环发生在稍后,当您迭代 itery 的每个元素时,而不是立即发生。

    (同样,您可以结合上述两个想法,例如,迭代器列表或列表迭代器,而不是迭代器迭代器或列表列表。)

    您甚至可以通过创建 Python 列表的一维数组并在其上调用 vectorize(lambda lst: filter(lambda x: x>0, sublist)) 来隐藏 NumPy 元素操作中的循环。但循环仍然存在。


    当然,您也可以通过间接循环来绕过循环。例如,使用递归:

    def filter_nonpositives(x):
        return x[:x[0]>0] + filter_nonpositives(x[1:])
    

    或者甚至将循环展开到某个最大尺寸:

    def filter_nonpositives(x):
        result = []
        if len(x) == 0:
            return result
        if x[0] > 0:
            result.append(x[0])
        if len(x) == 1:
            return result
        if x[1] > 0:
            result.append(x[1])
        if len(x) == 2:
            return result
        if x[2] > 0:
            result.append(x[2])
        # ... repeat as far as you want
        return result
    

    但无论哪种方式,你仍然有效地循环——而且你很难找到任何认为其中一个更 Pythonic 或更好的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 2018-03-24
      • 2016-08-05
      • 1970-01-01
      相关资源
      最近更新 更多