Поиск Python в списках списков

Я не мог использовать другие ответы в моем случае. Вместо этого я использовал нативный таймер Java.

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // this code will be executed after 2 seconds       
    }
}, 2000);
50
задан SilentGhost 20 July 2009 в 11:14
поделиться

8 ответов

У вас всегда будет цикл - кто-то может прийти с умным однострочником, который скрывает цикл внутри вызова map () или подобного, но он всегда будет там.

Я всегда предпочитаю иметь чистый и простой код, если только производительность не является основным фактором.

Вот, возможно, более питоническая версия вашего кода:

data = [['a','b'], ['a','c'], ['b','d']]
search = 'c'
for sublist in data:
    if sublist[1] == search:
        print "Found it!", sublist
        break
# Prints: Found it! ['a', 'c']

Она выходит из строя цикл, как только он находит совпадение.

(Кстати, у вас есть опечатка в ['b''d'] .)

42
ответ дан 7 November 2019 в 10:29
поделиться

все вышеперечисленное выглядит хорошо

, но хотите ли вы сохранить результат?

если да ...

вы можете использовать следующий

result = [element for element in data if element[1] == search]

, затем простой

len(result)

позволяет узнать, было ли что-то найдено (и теперь вы можете что-то делать с результатами)

конечно это не обрабатывает элементы, длина которых меньше единицы (которые вы должны проверить, если не знаете, что они всегда больше, чем length 1, и в этом случае следует ли использовать кортеж? (кортежи неизменяемы))

если вы знаете, что все элементы имеют заданную длину, вы также можете сделать это:

any(second == search for _, second in data)

или для len (data [0]) == 4:

any(second == search for _, second, _, _ in data)

... и я бы рекомендовал использовать

for element in data:
   ...

вместо

for i in range(len(data)):
   ...

(для будущего использования, , если вы не хотите сохранить или использовать «i» , и просто чтобы вы знали '0' не требуется, вам нужно использовать полный синтаксис, только если вы начинаете при ненулевом значении)

14
ответ дан 7 November 2019 в 10:29
поделиться
>>> the_list =[ ['a','b'], ['a','c'], ['b''d'] ]
>>> any('c' == x[1] for x in the_list)
True
16
ответ дан 7 November 2019 в 10:29
поделиться
>>> my_list =[ ['a', 'b'], ['a', 'c'], ['b', 'd'] ]
>>> 'd' in (x[1] for x in my_list)
True

Редактирование для добавления:

Оба ответа Дэвида с использованием any и мой с использованием в закончатся, когда они найдут совпадение, поскольку мы используем генератор выражений. Вот тест с использованием бесконечного генератора, чтобы показать, что:

def mygen():
    ''' Infinite generator '''
    while True:
        yield 'xxx'  # Just to include a non-match in the generator
        yield 'd'

print 'd' in (x for x in mygen())     # True
print any('d' == x for x in mygen())  # True
# print 'q' in (x for x in mygen())     # Never ends if uncommented
# print any('q' == x for x in mygen())  # Never ends if uncommented

Мне просто нравится просто использовать в вместо == и any .

9
ответ дан 7 November 2019 в 10:29
поделиться

Нет ничего плохого в использовании генерального exp, но если цель состоит в том, чтобы встроить цикл ...

>>> import itertools, operator
>>> 'b' in itertools.imap(operator.itemgetter(1), the_list)
True

Также должен быть самым быстрым.

3
ответ дан 7 November 2019 в 10:29
поделиться

У Маркуса есть один способ избежать использования слова для - вот другой, который должен иметь гораздо лучшую производительность в течение длительного времени the_list s ... :

import itertools
found = any(itertools.ifilter(lambda x:x[1]=='b', the_list)
4
ответ дан 7 November 2019 в 10:29
поделиться

Вот питонический способ сделать это:

data = [['a','b'], ['a','c'], ['b','d']]
search = 'c'
any(e[1] == search for e in data)

Или ... ну, я не собираюсь утверждать, что это «единственный истинный питонический способ», потому что в какой-то момент становится немного субъективным, что такое Pythonic, а что нет, или какой метод более Pythonic, чем другой. Но использование any () определенно более типично для Python, чем цикл for , как, например, Ответ РичиХиндла ,

Конечно, в реализация any , хотя она выходит из цикла, как только находит совпадение.


Так как мне было скучно, я сделал сценарий времени для сравнения производительности различных предложений, изменив некоторые из них по мере необходимости, чтобы API был таким же. Следует помнить, что самый быстрый - не всегда лучший, и быть быстрым - это определенно не то же самое, что быть Pythonic. При этом результаты ... странные. Очевидно, для циклов очень быстрые, чего я не ожидал, поэтому я бы отнесся к ним с недоверием, не понимая, почему они вышли именно так.

В любом случае, когда Я использовал список, определенный в вопросе, с тремя подсписками по два элемента в каждом, от самого быстрого до самого медленного. Я получаю следующие результаты:

  1. Ответ Ричи Хиндла с циклом for , тактовая частота 0,22 мкс
  2. Первое предложение Теренса Хонлеса , которое создает список, при 0,36 мкс
  3. Ответ Пьера-Люка Бедарда (последний блок кода) , при 0,43 мкс
  4. По существу связан между ответом Маркуса и для цикла из исходного вопроса , но различия между ними должны дать некоторое представление о том, насколько близки разные методы.

    Когда я использую более длинный список, все немного меняется. Я начал со списка в вопросе, с трех подсписок, и добавил еще 197 подсписок, в общей сложности 200 подсписок длины два. Используя этот более длинный список, вот результаты:

    1. Ответ Ричи Хиндла , за те же 0,22 мкс, что и с более коротким списком
    2. Ответ Коуди с использованием operator.itemgetter () , снова при 0,53 мкс
    3. Первое предложение Теренса Хонлеса , которое создает список, на 0,36 мкс
    4. Еще одна виртуальная связь между ответом Алекса Мартелли с ifilter () и Анонимный ответ , при 0,67 мкс
    5. Снова достаточно тесная связь между моим ответом, Брэндон Э. Тейлор ' s идентичный метод и второе предложение Теренса Хонлса с использованием any () , все приходящие на 0,81-0,82 мкс

    . Это те, которые сохраняют исходное время когда список расширяется. Остальные, которых нет, - это

    1. for цикл из исходного вопроса , при 1,24 мкс
    2. первое предложение Теренса Хонлеса , которое создает список , при 7,49 мкс
    3. ответ Пьера-Люка Бедара (последний блок кода) , при 8,12 мкс
    4. , ответ Маркуса , при 10,27 мкс
    5. ответ jojo , при 19,87 мкс
    6. И, наконец, ответ user27221 с использованием вложенных списков при 60,59 мкс
71
ответ дан 7 November 2019 в 10:29
поделиться
>>> the_list =[ ['a','b'], ['a','c'], ['b','d'] ]
>>> "b" in zip(*the_list)[1]
True

zip () берет кучу списков и группирует элементы вместе по индексу, эффективно транспонируя матрицу списков списков. Звездочка берет содержимое the_list и отправляет его в zip в качестве аргументов, поэтому вы фактически передаете три списка по отдельности, что и требуется для zip . Осталось только проверить, есть ли «b» (или что-то еще) в списке, состоящем из элементов с интересующим вас индексом.

1
ответ дан 7 November 2019 в 10:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: