Какой самый быстрый способ найти элемент списка в списке в python?

Список похож на этот:

[["12", "stuA", "stuB"], ["51", "stuC", "stuD"], ..., ["3234", "moreStuff", "andMore"]]

Теперь мне нужно найти элемент (получить индекс) только по его первому значению (например, "332"). Есть ли лучший способ сделать это, кроме повторения первого из них для сравнения с каждым значением?

код:

index = 0
for item in thelist:
    if item[0] == "332":
         print index

    index = index + 1

Ответ 1

Нет. Без итерации вы не можете его найти, если только список уже не отсортирован. Вы можете улучшить свой код следующим образом: enumerate и перечислить понимание.

[index for index, item in enumerate(thelist) if item[0] == "332"]

Это даст индексы всех элементов, где первый элемент 332.

Если вы знаете, что 332 происходит только один раз, вы можете сделать это

def getIndex():
    for index, item in enumerate(thelist):
       if item[0] == "332":
          return index

Ответ 2

Никто еще не упомянул об этом, поэтому я хочу - если вам нужно быстро найти элемент по его значению (и, предположительно, больше, чем один раз), вы должны изменить структуру данных, которую вы используете, чтобы поддерживать тип вам нужен доступ. Списки поддерживают быстрый доступ по индексу, но не по значению элемента. Если вы сохранили информацию в файле, указанном первым элементом в списках, вы могли бы быстро найти строки с помощью этого первого значения:

# Make a dict from the list of lists:
itemLookup = {item[0]: item for item in theList}

itemLookup["51"] # -> ["51", "stuC", "stuD"]

Итак, короткий ответ - нет (хотя есть быстрый способ использования бисекции, если список отсортирован), более длинный ответ - это словарь, если вы хотите быстро найти.

Ответ 3

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

import itertools
itertools.ifilter(lambda x: x[1][0] == "332", enumerate(theList)).next()[0]

и будет работать для получения более одного события, если вы измените его, чтобы использовать объект-генератор, вместо того, чтобы немедленно вызвать next, как я здесь.

Если это возможно, я бы предложил переместить данные в формат dict (OrderedDict, если ситуация имеет место) с этими целыми числами в качестве ключей (поскольку вы можете гарантировать, что они уникальны) или потенциально a pandas DataFrame с целыми числами в качестве индекса.

Ответ 4

Если ключ происходит ровно один раз,

zip(*thelist)[0].index("332")