파이썬에서 튜플 목록을 검색하는 방법


91

따라서 다음과 같은 튜플 목록이 있습니다.

[(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]

숫자 값이 무언가와 같은 튜플에 대해이 목록을 원합니다.

그래서 내가 할 경우 search(53)인덱스 값을 반환합니다2

이 작업을 수행하는 쉬운 방법이 있습니까?

답변:


95
[i for i, v in enumerate(L) if v[0] == 53]

68
설명해 주시겠습니까?
섀튼

17
단어로 설명 : L의 열거 목록에서 각 i, v에 대해 (i를 열거 목록에서 요소의 위치로 만들고 v 원래 튜플을 만듭니다) 튜플의 첫 번째 요소가 53인지 확인하고, 그렇다면 코드 결과를 추가합니다. 새로 생성 된 목록의 'for'앞에 i. my_function (i, v) 또는 또 다른 목록 이해가 될 수도 있습니다. 튜플 목록에는 첫 번째 값이 53 인 튜플이 하나뿐이므로 요소가 하나 인 목록이 표시됩니다.
djangonaut

6
나는 단지 [i for i, v in enumerate (L) if v [0] == 53] .pop () to have int value.
alemol 16.09.09

50

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 개의 요소 만 찾고 싶지만 전체 목록 이 처리된다는 것 입니다.

파이썬은 여기서 이상적인 간단한 구조를 제공합니다. 생성기 표현식 이라고합니다 . 다음은 그 예입니다.

# 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() 항목으로 사용하고 생성기에서 첫 번째 항목을 가져 오는 데 합니다.

이러한 방법이 더 큰 데이터 세트에서 어떻게 다르게 수행되는지 살펴 보겠습니다. 10000000 + 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}

뭐?! 최선의 경우 는 목록 이해력을 날려 버리지 만 최악의 경우가 목록 이해력을 능가 할 것으로 예상하지 못했습니다. 방법 것입니다? 솔직히, 나는 더 이상의 연구없이 만 추측 할 수있었습니다.

이 모든 것을 소금으로 가져 가십시오. 여기에서는 강력한 프로파일 링을 실행하지 않았으며 매우 기본적인 테스트 만 수행했습니다. 이것은 생성기 표현식이 이러한 유형의 목록 검색에 더 효과적이라는 것을 인식하기에 충분해야합니다.

이것은 모두 기본 내장 파이썬입니다. 우리는 아무것도 가져 오거나 라이브러리를 사용할 필요가 없습니다.

저는 Peter Norvig와 함께 Udacity cs212 코스 에서 검색하는이 기술을 처음 보았습니다 .


2
흥미 롭습니다. 테스트 결과 정말 빠릅니다
Grijesh Chauhan 2014

3
이것은 받아 들여진 대답이어야합니다. 생성기 표현식은 실행될 때 전체 출력 시퀀스를 구체화하지 않고 대신 표현식에서 한 번에 하나의 항목을 생성하는 반복자로 평가됩니다.
BoltzmannBrain

2
이것은 제 경우에 목록 이해보다 훨씬 빠릅니다. 감사합니다!
mindm49907

49

목록 이해력을 사용할 수 있습니다 .

>>> 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

29

튜플은 기본적으로 키-값 쌍 (파이썬)입니다 dict.

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]

2
우리는 영업 이익이 실제로 요구 것을 무시하면, 당신의 첫 대답은 "어떻게 파이썬에서 튜플의 목록을 검색하는"에 대한 가장 좋은 대답이라고 생각
릭 Westera

귀하의 첫 번째 답변은 제 목적에 유용했습니다. 항목이 dict에없는 경우 .get ()을 사용하는 것이 더 나을 수도 있습니다. l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] val = dict(l).get(53)
user1503941 2015

12

음 ... 음, 떠오르는 간단한 방법은 그것을 dict로 변환하는 것입니다.

d = dict(thelist)

및 액세스 d[53].

편집 : 죄송합니다, 처음으로 질문을 잘못 읽었습니다. 실제로 주어진 숫자가 저장된 색인을 얻고 싶은 것처럼 들립니다. 이 경우 시도하십시오

dict((t[0], i) for i, t in enumerate(thelist))

평범한 이전 dict변환 대신 . 그러면 d[53]2가됩니다.


6

목록이 길고 숫자가 반복 될 수 있다고 가정하면 Python sortedcontainers 모듈 에서 SortedList 유형을 사용하는 것이 좋습니다. . 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에 대해 이등분하면 슬라이스의 끝 인덱스를 찾을 수 있습니다. 이것은 허용되는 답변에 비해 긴 목록에서 훨씬 더 빠릅니다.


1

또 다른 방법입니다.

zip(*a)[0].index(53)

-2

[k for k, v in l if v == ' delicia ']

여기서 l은 튜플 목록입니다-[(1, "juca"), (22, "james"), (53, "xuxa"), (44, "delicia")]

그리고 그것을 dict로 변환하는 대신 llist 이해력을 사용하고 있습니다.

*Key* in Key,Value in list, where value = **delicia**


물론이지. @cosmoonot 감사합니다.
Mantej Singh 2017-04-25

여기 l은 튜플의 목록입니다-[(1, "juca"), (22, "james"), (53, "xuxa"), (44, "delicia")] 그리고 그것을 dict로 변환하는 대신, 우리는 llist 이해력을 사용하고 있습니다. ` 키, 목록에서 값에 어디 값 = DELICIA `
Mantej 싱
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.