【问题标题】:Getting the indices of all non-None items from a sub-list in Python?从 Python 的子列表中获取所有非无项的索引?
【发布时间】:2010-05-05 10:59:32
【问题描述】:

根据标题,我有一个这样的嵌套列表(嵌套列表是固定长度):

        # ID,  Name, Value
list1 = [[ 1, "foo",    10],
         [ 2, "bar",  None],
         [ 3, "fizz",   57],
         [ 4, "buzz", None]]

我想返回一个列表(项目数等于来自list1 的子列表的长度),其中子列表是没有 None 作为第 X 项的行的索引,即:

[[non-None ID indices], [non-None Name indices], [non-None Value indices]]

list1为例,结果应该是:

[[0, 1, 2, 3], [0, 1, 2, 3], [0, 2]]

我目前的实现是:

indices = [[] for _ in range(len(list1[0]))]
for i, row in enumerate(list1):
    for j in range(len(row)):
        if not isinstance(row[j], types.NoneType):
            indices[j].append(i)

...可行,但可能很慢(列表的长度为数十万)。

有没有更好/更有效的方法来做到这一点?

编辑:

我已将上述 for 循环重构为嵌套列表理解(类似于 SilentGhost 的答案)。以下行给出了与我最初的实现相同的结果,但运行速度大约快了 10 倍。

[[i for i in range(len(list1)) if list1[i][j] is not None] for j in range(len(log[0]))]

【问题讨论】:

  • 您编辑的变体无效,因为list1[i] 始终不是None 例如,list1[0][1, "foo", 10](注意:[None, None, None] is not None)。
  • 谢谢 - 我想我现在已经修好了。

标签: python list list-comprehension


【解决方案1】:
>>> [[i for i, j in enumerate(c) if j is not None] for c in zip(*list1)]
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 2]]

在 python-2.x 中,您可以使用 itertools.izip 而不是 zip 来避免生成中间列表。

【讨论】:

    【解决方案2】:
    [[i for i in range(len(list1)) if list1[i] is not None] for _ in range(len(log[0]))]
    

    上面的内容似乎比我原来的帖子快 10 倍。

    【讨论】:

      【解决方案3】:
      import numpy as np
      
      map(lambda a: np.not_equal(a, None).nonzero()[0], np.transpose(list1))
      # -> [array([0, 1, 2, 3]), array([0, 1, 2, 3]), array([0, 2])]
      

      【讨论】:

      • 这个变体比@SilentGhost 的变体慢 3 倍(在某些输入上)。
      猜你喜欢
      • 2015-03-26
      • 2019-03-23
      • 1970-01-01
      • 2015-11-02
      • 2014-04-20
      • 2013-03-30
      • 2019-05-24
      • 2014-08-16
      • 2013-06-15
      相关资源
      最近更新 更多