【问题标题】:How do I get a list of indices of non zero elements in a list?如何获取列表中非零元素的索引列表?
【发布时间】:2011-05-05 21:56:49
【问题描述】:

我有一个总是只包含 1 和 0 的列表。 我需要获取列表的非零索引列表:

a = [0, 1, 0, 1, 0, 0, 0, 0]
b = []
for i in range(len(a)):
    if a[i] == 1:  b.append(i)
print b

实现这一目标的“pythonic”方式是什么?

【问题讨论】:

    标签: list python list-comprehension


    【解决方案1】:
    [i for i, e in enumerate(a) if e != 0]
    

    【讨论】:

    • 让我想起了 itertools.compress,但它会压缩而不是枚举。
    • @Sachin_ruk:不太可能。另一方面,它不需要 NumPy。
    【解决方案2】:

    不是一个真正的“新”答案,但numpy 也内置了这个。

    import numpy as np
    a = [0, 1, 0, 1, 0, 0, 0, 0]
    nonzeroind = np.nonzero(a)[0] # the return is a little funny so I use the [0]
    print nonzeroind
    [1 3]
    

    【讨论】:

    • 太酷了!我需要它来在 Cinema-4D 中编写一些 Python 脚本,所以当时仅仅为此创建一个库没有意义。 numpy 看起来很不错!感谢分享!
    • 我也更喜欢 numpy 然后另一个答案...这更容易理解...它更合乎逻辑,如果您来自 matalb 则更合乎逻辑:-)
    【解决方案3】:

    由于 THC4k 提到了 compress(python2.7+ 可用)

    >>> from itertools import compress, count
    >>> x = [0, 1, 0, 1, 0, 0, 0, 0]
    >>> compress(count(), x)
    <itertools.compress object at 0x8c3666c>   
    >>> list(_)
    [1, 3]
    

    【讨论】:

    • +1 表示聪明,尽管事实上几乎不存在的解释通过使用“_”最后结果绑定到作为参数传递给 @ 的迭代器对象变得更加模糊987654322@函数/类型。
    【解决方案4】:

    只是想为上一个 asnwer 的“有趣”输出添加解释。结果是一个元组,其中包含矩阵每个维度的索引向量。在这种情况下,用户正在处理被认为是 numpy 中的向量的内容,因此输出是带有一个元素的元组。

    import numpy as np
    a = [0, 1, 0, 1, 0, 0, 0, 0]
    nonzeroind = np.nonzero(a) 
    print nonzeroind
    (array([1, 3]),)
    

    【讨论】:

      【解决方案5】:

      两个答案与列表长度的时间比较

      a = [int(random.random()>0.5) for i in range(10)]
      %timeit [i for i, e in enumerate(a) if e != 0]
      683 ns ± 14 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
      %timeit np.nonzero(a)[0]
      4.43 µs ± 102 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      
      a = [int(random.random()>0.5) for i in range(1000)]
      %timeit [i for i, e in enumerate(a) if e != 0]
      53.1 µs ± 2.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
      %timeit np.nonzero(a)[0]
      73.8 µs ± 2.71 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
      
      a = [int(random.random()>0.5) for i in range(100000)]
      %timeit [i for i, e in enumerate(a) if e != 0]
      5.86 ms ± 79.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      %timeit np.nonzero(a)[0]
      6.61 ms ± 14.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      

      列表长度为100000,改变列表中的个数

      a = [int(random.random()>0.1) for i in range(100000)]
      %timeit [i for i, e in enumerate(a) if e != 0]
      6.45 ms ± 28.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      %timeit np.nonzero(a)[0]
      5.74 ms ± 9.25 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      
      a = [int(random.random()>0.9) for i in range(100000)]
      %timeit [i for i, e in enumerate(a) if e != 0]
      4.69 ms ± 12.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      %timeit np.nonzero(a)[0]
      5.74 ms ± 6.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      

      个数只影响第一个选项。 np.nonzero() 对于大量非零元素更好。如果长度小于 10000,则第一个选项更快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-03
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多