2016-09-01 2 views
4

목록을 파이썬으로 분류하는 가장 좋은 방법은 무엇입니까? 예를 들어Python의 목록 분류

:

totalist is below 

totalist[1] = ['A','B','C','D','E'] 
totalist[2] = ['A','B','X','Y','Z'] 
totalist[3] = ['A','F','T','U','V'] 
totalist[4] = ['A','F','M','N','O'] 

처음 두 항목 ['A','B'], 기본적으로 list[1]list[2]을 어디에 나는 목록을 얻을하고 싶은 말은. 한 번에 하나의 항목을 반복하지 않고도 이들을 쉽게 얻을 수 있습니까? 이런 식으로?

if ['A','B'] in totalist 

나는 작동하지 않습니다.

+3

코드가 무엇을 시도한다? –

+1

답변을 제안 할 때 어떤 형식으로도 반복하지 않고이를 해결할 방법이 없습니다. 데이터를 효율적으로 확인하는 것이 큰 우선 순위라면 데이터를 어떻게 표현하는지 다시 작성해야합니다. 향상된 속도를 위해 공간의 복잡성을 희생합니다. 예를 들어 목록을 만들 때 어떤 행이 속성을 만족하는지 메모 할 수 있습니다. – gowrath

답변

3

각 목록의 처음 두 요소를 확인할 수 있습니다.

for totalist in all_lists: 
    if totalist[:2] == ['A', 'B']: 
     # Do something. 

참고 : Kasramvd 제안 한 - 라이너 솔루션도 아주 좋은입니다. 내 솔루션을 더 읽기 쉽게 발견했습니다. 비록 내포가 보통의 for 루프보다 약간 빠르다는 것을 말해야하지만. (어느 것이 나 자신을 테스트했는지)

+0

이것은 위대한, 잘 모르겠 왜 downvote있어,하지만 난 당신을 위해 그것을 반박했다. – bravosierra99

+0

@ bravosierra99 감사합니다, OP는 당신이 요소를 반복하지 않아도되는 해결책이 있다면 해결책을 물었습니다. 아마 내가 downvote를 얻었습니다. 그러나 나는 모든 목록을 반복하지 않고 이것을 달성 할 수있는 방법을 보지 못합니다. – Rockybilly

+0

나는 그가 모든 목록에있는 모든 개별 항목을 반복하지 않고 의미한다고 가정합니다. 당신은 목록을 통해 반복하거나 각 하나를 확인할 수 없습니다 .... – bravosierra99

1

기본적으로 파이썬에서는 중첩 목록을 사용하여이 작업을 수행 할 수 없습니다. 당신이 인덱스 원하는 경우

>>> [sub for sub in totalist if sub[:2] == ['A', 'B']] 
[['A', 'B', 'C', 'D', 'E'], ['A', 'B', 'X', 'Y', 'Z']] 

: 하위 목록의 처음 두 항목으로 구성 목록을 비교하여

를 사용하여 간단한 지능형리스트 : 당신은 최적화 된 방법을 찾고 있다면 그러나 여기에 몇 가지 방법입니다

>>> [ind for ind, sub in enumerate(totalist) if sub[:2] == ['A', 'B']] 
[0, 1] 

을 그리고 여기에 용량이 큰 데이터 세트를 처리 할 때 꽤 많이 최적화 NumPy와의 접근 방식 : enumerate 사용

또한 당신이 당신이 기능적인 방법을 찾고 루프를 사용하지 않으려면 파이썬의 이해를 나열하는 대신, 당신은 지능형리스트로 최적화되지 않는 filter 기능을 사용할 수 있습니다

>>> list(filter(lambda x: x[:2]==['A', 'B'], totalist)) 
[['A', 'B', 'C', 'D', 'E'], ['A', 'B', 'X', 'Y', 'Z']] 
+0

FYI,'filter'는 완벽하게 최적화되어 있습니다. _ 프리디 케이트 함수가 C_로 구현 된 내장 함수이고 (당신의 입력은 충분히 길다); 이 경우 일반적으로 동등한 genexpr/listcomps보다 빠르게 실행됩니다. 만약 genexpr/listcomp이 인라인 할 수있는'lambda '가 필요하다면, 느리게 진행될 것이고, genexpr/listcomp에서 피할 수없는'def' 함수를 사용한다면, 보통 성능면에서 비슷합니다. , 단지). 'filter'는 진보되었고, genexpr/listcomp 만 사용하는 것이 완벽 합니다만, 이해한다면 속도 향상을 위해 사용할 수 있습니다. – ShadowRanger

+0

@ShadowRanger 그래, 나도 알아,하지만 주셔서 감사합니다. – Kasramvd

1

이렇게 할 수 있습니다.

>>> for i in totalist: 
...  if ['A','B']==i[:2]: 
...    print i 
+0

나는 대답을 썼다. 그리고 나는 그가 똑같은 것을 썼음을 알았다. :-) –

+0

우리 모두에게 일어난 일입니다! –

0

귀하는 성능 (비용)에 대해 염려하고 있다는 것을 의미합니다. 이 작업을 수행해야하는 경우 성능에 대해 걱정할 경우 다른 데이터 구조가 필요합니다. 이렇게하면 목록을 만들 때 약간의 "비용"이 추가되지만 필터링 할 때 시간을 절약 할 수 있습니다.

첫 번째 두 요소를 기반으로 필터링해야 할 필요가있는 경우 (첫 번째 n 요소로 일반화되지 않음) 해당 목록이 추가 될 때 해당 키가 터플 인 사전에 추가됩니다 처음 두 요소 중 하나이며 항목은 목록의 목록입니다.

당신은 단순히 dict 조회를하여 목록을 검색 할 수 있습니다. 이것은 쉽게 수행 할 수 있으며 목록을 만드는 동안 메모리와 시간을 거의 들지 않으면 서 잠재적으로 큰 속도 향상을 가져올 것입니다.

+0

처음 두 요소가 항상 존재하지는 않습니다. 목록을 살펴 보니 계속 증가 할 것입니다. 기본적으로 목록은 경로이며 분기별로 경로를 분류하는 트리입니다. 위에서 언급 한 if 문을 사용합니다. – user1179317

2

그냥 재미를 위해, itertools 솔루션은 C 층에 당 요소 작업을 밀어 :

from future_builtins import map # Py2 only; not needed on Py3 
from itertools import compress 
from operator import itemgetter 

# Generator 
prefixes = map(itemgetter(slice(2)), totalist) 
selectors = map(['A','B'].__eq__, prefixes) 

# If you need them one at a time, just skip list wrapping and iterate 
# compress output directly 
matches = list(compress(totalist, selectors)) 

이 모든 수에 1을 늘어선 :

matches = list(compress(totalist, map(['A','B'].__eq__, map(itemgetter(slice(2)), totalist)))) 

그러나 나는 권하고 싶지 않다 그것. totalist가 발생하지 재 반복 가능한 순서있을 경우 부수적으로, 당신은 추가를 두 배로 itertools.tee을 사용할 것 :

totalist, forselection = itertools.tee(totalist, 2) 

forselection 이상 mapprefixes의 정의를 변경하지 totalist; compress은 두 개의 반복자를 병렬로 반복하므로, tee은 의미있는 메모리 오버 헤드를 가지지 않습니다.

물론 다른 사람들도 언급했듯이 C로 이동하더라도 이것은 선형 알고리즘입니다. 이상적으로는 collections.defaultdict(list)과 같은 것을 사용하여 각 list (tuple으로 변환하여 dict 키로 변환)의 두 요소 접두사에서 listlist (해당 접두사가있는 문자)으로 매핑하는 것이 좋습니다. 그런 다음 N list을 선형 검색하는 대신 일치하는 접두사가있는 항목을 찾으려면 totaldict['A', 'B']을 입력하고 O(1) 검색 (결과는 고정 된 작업이 아닌 고정 된 슬라이스가 아님)으로 결과를 얻습니다.

예 미리 계산 작업 :

from collections import defaultdict 

totaldict = defaultdict(list) 
for x in totalist: 
    totaldict[tuple(x[:2])].append(x) 

# Optionally, to prevent autovivification later: 
totaldict = dict(totaldict) 

그럼 당신은 단지 어떤 두 요소 접두어 효과적으로 즉시 matches를 얻을 수 있습니다 :

matches = totaldict['A', 'B'] 
+1

정말 재미 있어요! 당신은 재미있는 요소에 대한 표를 얻지 만, 이것이 허용 된 대답이되도록하지 마시기 바랍니다! :) –

+0

@RolfofSaxony : :-) 나는 itertools를 좋아한다; 거의 확실하게 여기서는 적합하지 않지만, 일반적인 패턴은 실제로 다른 용도로 잘 사용하는 방법에 대한 적절한 예입니다. OP의 경우에, 나는 거의'defaultdict (list)'경로로 간다. – ShadowRanger

+0

@RolfofSaxony 재미 있고, 일부 기능을 결합하여 불필요한 작업을 수행하는 것은 올바른 방법이 아닙니다. 특히 더 간단하고 빠른 방법으로 수행 할 수있는 간단한 작업에 특히 적합합니다. – Kasramvd