Итак, у меня есть список таких кортежей:
[(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]
Мне нужен этот список для кортежа, числовое значение которого чему-то равно.
Так что, если я это сделаю, search(53)
он вернет значение индекса2
Есть простой способ сделать это?
tl; dr
Выражение генератора , вероятно , является наиболее производительным и простым решением вашей проблемы:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] result = next((i for i, v in enumerate(l) if v[0] == 53), None) # 2
Объяснение
Есть несколько ответов, которые обеспечивают простое решение этого вопроса с помощью списков. Хотя эти ответы совершенно верны, они не оптимальны. В зависимости от вашего варианта использования внесение нескольких простых изменений может дать значительные преимущества.
Основная проблема, которую я вижу при использовании понимания списка для этого варианта использования, заключается в том, что будет обработан весь список , хотя вы хотите найти только 1 элемент .
Python предоставляет простую конструкцию, которая здесь идеально подходит. Это называется выражением генератора . Вот пример:
# Our input list, same as before l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] # Call next on our generator expression. next((i for i, v in enumerate(l) if v[0] == 53), None)
Мы можем ожидать, что этот метод будет работать в основном так же, как составление списков в нашем тривиальном примере, но что, если мы работаем с большим набором данных? Вот здесь и проявляется преимущество использования метода генератора. Вместо того, чтобы создавать новый список, мы будем использовать ваш существующий список в качестве нашего итеративного и использовать
next()
для получения первого элемента из нашего генератора.Давайте посмотрим, как эти методы по-разному работают с некоторыми большими наборами данных. Это большие списки, состоящие из 10 000 000 + 1 элементов, с нашей целью в начале (лучший) или конец (худший). Мы можем убедиться, что оба этих списка будут работать одинаково, используя следующее понимание списка:
Составьте список
"Худший случай"
worst_case = ([(False, 'F')] * 10000000) + [(True, 'T')] print [i for i, v in enumerate(worst_case) if v[0] is True] # [10000000] # 2 function calls in 3.885 seconds # # Ordered by: standard name # # ncalls tottime percall cumtime percall filename:lineno(function) # 1 3.885 3.885 3.885 3.885 so_lc.py:1(<module>) # 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
"Лучший случай"
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000) print [i for i, v in enumerate(best_case) if v[0] is True] # [0] # 2 function calls in 3.864 seconds # # Ordered by: standard name # # ncalls tottime percall cumtime percall filename:lineno(function) # 1 3.864 3.864 3.864 3.864 so_lc.py:1(<module>) # 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Генератор выражений
Вот моя гипотеза для генераторов: мы увидим, что генераторы будут работать значительно лучше в лучшем случае, но точно так же в худшем случае. Это увеличение производительности в основном связано с тем, что генератор вычисляется лениво, то есть он будет вычислять только то, что требуется для получения значения.
Худший случай
# 10000000 # 5 function calls in 1.733 seconds # # Ordered by: standard name # # ncalls tottime percall cumtime percall filename:lineno(function) # 2 1.455 0.727 1.455 0.727 so_lc.py:10(<genexpr>) # 1 0.278 0.278 1.733 1.733 so_lc.py:9(<module>) # 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} # 1 0.000 0.000 1.455 1.455 {next}
Лучший случай
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000) print next((i for i, v in enumerate(best_case) if v[0] == True), None) # 0 # 5 function calls in 0.316 seconds # # Ordered by: standard name # # ncalls tottime percall cumtime percall filename:lineno(function) # 1 0.316 0.316 0.316 0.316 so_lc.py:6(<module>) # 2 0.000 0.000 0.000 0.000 so_lc.py:7(<genexpr>) # 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} # 1 0.000 0.000 0.000 0.000 {next}
КАКИЕ?! Лучший случай разрушает понимание списка, но я не ожидал, что наш худший случай превзойдет понимание списка в такой степени. Как так? Честно говоря, без дальнейших исследований я мог только предполагать.
Отнеситесь ко всему этому с недоверием, я не проводил здесь какого-либо надежного профилирования, а просто проводил очень простое тестирование. Этого должно быть достаточно, чтобы понять, что выражение генератора более производительно для этого типа поиска по списку.
Обратите внимание, что это все базовый встроенный питон. Нам не нужно ничего импортировать или использовать какие-либо библиотеки.
Впервые я увидел эту технику поиска на курсе Udacity cs212 с Питером Норвигом.
источник
Вы можете использовать понимание списка :
>>> a = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] >>> [x[0] for x in a] [1, 22, 53, 44] >>> [x[0] for x in a].index(53) 2
источник
Ваши кортежи в основном представляют собой пары ключ-значение - python
dict
--so:l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] val = dict(l)[53]
Изменить - ага, вы говорите, что хотите значение индекса (53, "xuxa"). Если это действительно то, что вы хотите, вам придется перебирать исходный список или, возможно, создать более сложный словарь:
d = dict((n,i) for (i,n) in enumerate(e[0] for e in l)) idx = d[53]
источник
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] val = dict(l).get(53)
Хм ... ну, простой способ, который приходит в голову, - это преобразовать его в диктовку
и доступ
d[53]
.РЕДАКТИРОВАТЬ : Ой, неправильно прочитал свой вопрос в первый раз. Похоже, вы действительно хотите получить индекс, в котором хранится данное число. В таком случае попробуйте
dict((t[0], i) for i, t in enumerate(thelist))
вместо простого старого
dict
преобразования. Тогдаd[53]
было бы 2.источник
Предположив список может быть длинным и числа могут повторяться, рассмотреть вопрос об использовании SortedList типа из модуля Python sortedcontainers . Тип SortedList автоматически упорядочивает кортежи по номерам и обеспечивает быстрый поиск.
Например:
from sortedcontainers import SortedList sl = SortedList([(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]) # Get the index of 53: index = sl.bisect((53,)) # With the index, get the tuple: tup = sl[index]
Это будет работать намного быстрее, чем предложение понимания списка при выполнении двоичного поиска. Предложение словаря будет еще быстрее, но не будет работать, если могут быть повторяющиеся числа с разными строками.
Если есть повторяющиеся числа с разными строками, вам нужно сделать еще один шаг:
end = sl.bisect((53 + 1,)) results = sl[index:end]
Разделив пополам 54, мы найдем конечный индекс для нашего среза. Это будет значительно быстрее для длинных списков по сравнению с принятым ответом.
источник
Просто другой способ.
zip(*a)[0].index(53)
источник
[k вместо k, v в l, если v == ' delicia ']
здесь l - список кортежей - [(1, "juca"), (22, "james"), (53, "xuxa"), (44, "delicia")]
И вместо того, чтобы преобразовывать его в dict, мы используем понимание llist.
*Key* in Key,Value in list, where value = **delicia**
источник