Getting indices of all non-None elements from a sub-list in Python?

As per the title, I have nested lists like this (nested list is fixed length):

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

      

I would like to return a list (number of elements equal to the length of the sub-list from list1

), where the sub-lists are the indices of the strings without None as their Xth element, that is:

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

      

Using list1

as an example, the result should be:

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

      

My current implementation:

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)

      

... which works, but can be slow (lists are hundreds of thousands long).

Is there a better / more efficient way to do this?

EDIT:

I've refactored the above for loops on nested lists (similar to SilentGhost's answer). The next line gives the same result as my original implementation, but is about 10x faster.

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

      

+2


a source to share


3 answers


>>> [[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]]

      



in python-2.x you can use itertools.izip

instead zip

to avoid generating an intermediate list.

+5


a source


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

      



The above seems to be about 10x faster than my original post.

+1


a source


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

      

0


a source







All Articles