Python: перебор списков, соответствующих значению, и его изменение

#python #list #loops

#python #Список #циклы

Вопрос:

Какой будет самый быстрый способ сделать это? У меня есть список списков, и я должен перебирать его в поисках определенного значения в каждом из подсписков. Как только значение найдено, я должен добавить значение в другой отдельный список, а затем изменить значение, которое я нашел. Я начал делать это

 for x in f
    if 'nan' in x:
        ef.append(1.0)
    else:
        ef.append(0.0)
  

f — это список списков, поэтому я перебираю каждый список x и проверяю, есть ли значение nan среди элементов подсписка. Если среди элементов подсписка x есть хотя бы одно значение nan, я добавляю 1.0 к ef, но если его нет, я добавляю 0.0. Теперь мне нужно сделать это, но в то же время я должен изменить все значения nan в каждом подсписке на 1.0. Поэтому я хочу сделать что-то вроде

 for x in f:
    if 'nan' in x:
        ef.append(1.0)
        x[position of nans] = 1.0
    else:
        ef.append(0.0)
  

Есть ли способ сделать это в этом цикле или я должен выполнить цикл снова? Я имею дело с очень большими объемами данных, поэтому я хотел сохранить их как можно быстрее.

Ответ №1:

Сложность для чего-то подобного линейна, вы не могли бы сделать лучше, потому что вам нужно проверять каждый элемент по крайней мере один раз. Предполагая, что вы хотите добавить 1 или 0 в ef список только один раз для каждого подсписка, сработает что-то вроде этого:

 f = [[1, 'nan'], [2, 'nan', 'nan']]
ef = []

for x in f:
    found = False
    for pos, e in enumerate(x):
        if e == 'nan':
            x[pos] = 1
            found = True
    ef.append(1 if found else 0)

print f, ef
  

Живой пример на ideone здесь.

Синхронизация на моем ноутбуке (включает в себя построение списка):

 $ time python test.py 
numElements = 15000000

real    0m1.908s
user    0m1.879s
sys 0m0.028s
  

Комментарии:

1. Эй, извините, я немного изменил ваш пример, потому что в вопросе есть только один, 1 прикрепленный к ef для каждой записи в, f которая содержит 'nan' , а не для каждого 'nan' : ideone.com/Z4ee3h

2. Спасибо, да, достаточно справедливо, я не понял из вопроса, когда нужно присоединить 1. Я думаю, что OP может разобраться в этом сам, хотя вопрос был больше о том, есть ли более быстрый способ сделать это? 🙂

3. @paul-g да, спасибо. Приведенный выше плакат правильный, но ваш ответ действительно помогает мне. Я немного изменил формулировку, чтобы сделать ее более понятной.

4. @paul-g спасибо, что показал мне ideone кстати, это так полезно!!

5. @Atirag хорошо, я обновил свой ответ, чтобы добавлять только один раз в каждый подсписок? 🙂

Ответ №2:

Вместо использования list.append() быстрее инициализировать один раз, используя понимание списка:

 ef = [[item if item != 'nan' else 1 for item in list] for list in f]
  

Это позволяет избежать необходимости находить конец списка после каждой вставки и является более эстетичным.

Комментарии:

1. хммм… но элемент там никогда не меняется с nan на 1, верно? Мне нужно изменять элемент, найденный в подсписке, на 1 каждый раз, когда найден nan, а nan можно найти для многих разных элементов внутри каждого списка. ef должен содержать только одну запись для каждого подсписка, а не для каждого найденного nan