Получение индексов всех элементов, отличных от None, из подсписка в Python?

Согласно названию, у меня есть такие вложенные списки (вложенный список имеет фиксированную длину):

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

person Noah    schedule 05.05.2010    source источник
comment
ваш отредактированный вариант недействителен, потому что list1[i] всегда не None, например, list1[0] это [1, "foo", 10] (примечание: [None, None, None] is not None).   -  person jfs    schedule 05.05.2010
comment
Спасибо - я думаю, что исправил это сейчас.   -  person Noah    schedule 06.05.2010


Ответы (3)


>>> [[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, чтобы избежать создания промежуточного списка.

person SilentGhost    schedule 05.05.2010

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

Вышеприведенное кажется примерно в 10 раз быстрее, чем мой оригинальный пост.

person Noah    schedule 05.05.2010

person    schedule
comment
этот вариант в 3 раза медленнее, чем у @SilentGhost (на некоторых входных данных). - person jfs; 05.05.2010