2016-09-24 4 views
1

나는 반복자 iterator과 인덱스 목록 indices (가능한 반복)을 가지고 있으며, 나는 그 반복자에서 그 요소들을 추출하고 싶다. 지금 내가하고있는 순간에파이썬 반복자에 대한 인덱스

indices = sorted(indices) 
deltas = [indices[0]] + [indices[i+1] - indices[i] for i in range(len(indices) - 1)] 
output = [] 
for delta in deltas: 
    for i in range(delta): 
     datum = next(iterator) 
    output.append(datum) 

루프의 두 레이어가 필요합니까? itertools으로 트릭을 놓치고 있습니까?

+4

예, 수행하려는 것을 재현하는 데 도움이되는 몇 가지 정렬 예제를 제공해야합니다. 나는 인덱스가'int'의 일부 목록이지만, 다음과 같은 라인을 가지고 있습니다 :'indices [0] + [indices [i + 1] - indices [i] 범위의 i (len (indices) - 1)]' 이 경우 작동합니다 -'int'에'list'를 추가 할 수 없습니다. –

+1

또한 인덱스는 일종의 시퀀스 유형을 의미합니다. 'iterators'는 시퀀스에 대해 단일 패스를 사용합니다 : * 인덱스를 시퀀스로 직접 인덱싱하지 않는 이유는 무엇입니까? –

+0

코드에 비해 명확한 개선 사항은 없다고 생각합니다. 'itlice'와 같은 itertools 함수는 반복 된 인덱스를 가지고 있기 때문에 당신을 위해 작동하지 않을 것입니다. 한 가지 고려해야 할 점은 : iterator가 단지 적은 양의 데이터만을 포함하고 (메모리에 적합 할 수 있고 인덱스의 수보다 더 큰 순서가 아닌) 데이터를 단순히 소비하는 것이 더 쉬울 수도 있습니다. 목록을 채우고, 사소한 목록 이해를 사용하여 요청 된 값을 가져옵니다. – Blckknght

답변

0

당신은 확실히 더블 루프가 필요하지 않습니다 당신은 C에 의해 수표의 비용을 줄일 수

[datum for i, datum in enumerate(x) if i in indices] 

: 당신이합니다 (sort을하지만 피) 검사에 대한 오버 헤드 발생으로 지수의 매우 낮은 번호에 대한 지능형리스트 전환 indices ~ set.

indices = set(indices) 
[datum for i, datum in enumerate(x) if i in indices] 

업데이트 : 첫 번째와 세 번째 옵션은 겨우 900 밀리 초에서 타이밍과 거의 비슷하다 (약간 나는 set 건설을 통해 sort의 성능을보고 관심이있을 것이다 (세트 조회는 O (1)이다) 처음부터 끝까지) 10,000,000 개의 항목 중에서 1000 개의 임의의 색인을 선택합니다. OP의 코드는 약 1.2 초 만에 실행되었습니다.

+0

너무 빨리 입력하는 중 ... 죄송합니다. – AChampion

0

메모리가 제약 조건이 아니라면 max 인덱스를 찾고 해당 최대 인덱스까지 반복자 값의 배열을 채울 것입니다. 어쨌든 중간 값을 계산해야하므로 델타를 계산하여 실제로 아무것도 얻지 못합니다.

it = iter(sorted(indices)) 
index = next(it) 
for i, datum in enumerate(iterator): 
    if i != index: 
     continue 
    output.append(datum) 
    try: 
     index = next(it) 
    except StopIteration: 
     break 

또한이 작업을 수행 할 수 있습니다 단일 루프 및 생성 델타없이이 작업을 수행 할 수 있지만 체크 코드를 더 복잡하게로

max_index = max(indices) 
data = [v for v in itertools.islice(iterator, max_index + 1)] 
values = [data[i] for i in indices]