2010-12-21 4 views
16

목록 병합의 반대입니다.하위 목록 만들기

주어진리스트 및 길이 n은 길이 n의 서브리스트의리스트를 반환한다.

def sublist(lst, n): 
    sub=[] ; result=[] 
    for i in lst: 
     sub+=[i] 
     if len(sub)==n: result+=[sub] ; sub=[] 
    if sub: result+=[sub] 
    return result 

예 :

목록 인 경우 :

[1,2,3,4,5,6,7,8] 

그리고 n은 :

3 

반환 :

[[1, 2, 3], [4, 5, 6], [7, 8]] 

더 웅변/간결한 방법이 있습니까?

(위의 맥락에서) 목록에 목록을 추가 할 때 선호 무엇 여담 :

list1+=[list2] 

또는를 :

list1.append(list2) 

을 감안할 때 그 (Summerfeild의 '파이썬 3 프로그래밍'에 따라) 그들은 동일합니까?

감사합니다.

from itertools import islice 

def take(n, it): 
    "Return first n items of the iterable as a list" 
    return list(islice(it, n)) 

def split(it, size): 
    it = iter(it) 
    size = int(size) 
    ret = take(size, it) 
    while ret: 
     yield ret 
     ret = take(size, it) 

편집 : 당신의 asside에 대해서는, 항상 list.append를 사용 (저쩌구

답변

15

이러한 목록을 사용하여 구성 할 수있는 list comprehension :

In [19]: import itertools 
In [20]: list(itertools.izip_longest(*[iter(seq)]*3)) 
Out[20]: [(1, 2, 3), (4, 5, 6), (7, 8, None)] 

하지만없는 요소의 값이 없음으로 가득 참고 :이 또한 grouper idiom입니다

In [17]: seq=[1,2,3,4,5,6,7,8] 
In [18]: [seq[i:i+3] for i in range(0,len(seq),3)] 
Out[18]: [[1, 2, 3], [4, 5, 6], [7, 8]] 

. izip_longest은 None 이외가 필요한 경우 fillvalue 매개 변수를 사용할 수 있습니다.


list1+=[list2] - 브래킷 이번에는 주목 - list1.append(list2) 동일하다. 코드를 작성할 때 나의 최우선 순위는 가독성이다. 속도가 아님. 이런 이유로 list1.append(list2)으로 갈 것입니다. 가독성은 주관적이지만, 아마도 당신이 익숙한 관용구에 크게 영향을받습니다.

행복하게,이 경우, 가독성과 속도가 일치하는 것 :

에 대한
In [41]: %timeit list1=[1,2,3]; list1.append(list2) 
1000000 loops, best of 3: 612 ns per loop 

In [42]: %timeit list1=[1,2,3]; list1+=[list2] 
1000000 loops, best of 3: 847 ns per loop 
+0

감사합니다. unutbu, 이것이 얼마나 평범한 지 이해력을 사용하고 있는지를 웃어 봐야합니다. 그 (것)들을 공부하는 나의 필요를 이해한다. + = vs append에 관해서는, 나는 list1 + = list2와 list1.append (list2)가 아니라 list1 + = [list2]를 list1.append (list2)와 비교했을 때 차이점을 이해할 수 있습니다. 감사합니다 훌륭한 답변/토론. –

+0

@Michael Puckett : 질문의 두 번째 부분을 잘못 읽었습니다. 편집 중 ... – unutbu

+0

감사합니다. unutbu - append ftw. :) –

1

나는이 분할 기능 (그냥이 나열보다는 어떤 반복자와 함께 작동하지만) 당신이 찾고있는 무엇을합니까 생각), 그것은 나를 더 관용적으로 느낀다. 그러나 나는 그들이 기능적으로 동등하다고 믿는다. 목록

+2

django 것들이 필요하지 않습니다. –

+0

@Xavier 그래, 그것을 제거했습니다. (원래 장고 템플릿 필터로 이것을 사용했습니다.) –

+0

Thanks Gabriel. –

6

방법 다음 (x는 목록입니다) :

[x[i:i+3] for i in range(0, len(x), 3)] 

n!=3에 대한 일반화 간단하다 .

두 번째 질문에 대해서는 동일하므로 스타일의 문제라고 생각합니다. 그러나 confusing append with extend이 아닌지 확인하십시오.

+0

감사합니다 aix, 목록 이해가 확실히 갈 길. 나는 그것을 생각하지 않았지만 나는 파이썬 멍청이라는 사실을 안타까워했다. –

5

이 기능은 반복 가능한 모든 종류의 (길이를 알고뿐만 아니라 순서) 취할 수 있습니다

import itertools 

def grouper(n, it): 
    "grouper(3, 'ABCDEFG') --> ABC DEF G" 
    it = iter(it) 
    return iter(lambda: list(itertools.islice(it, n)), []) 

print(list(grouper(3, [1,2,3,4,5,6,7,8,9,10]))) 
# [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] 
+0

감사합니다 tokland, 잘 알고 있습니다. –

0

내가 아는을, 그것은 brainfuck처럼 보이지만 작품이다 : 일부

>>> a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] 
>>> n = 3 
>>> [i for j in [[a[t:t+n] for x in a[:1:t+1] if (t%n)==False] for t in range(len(a))] for i in j] 
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]] 

>>> n = 4 
>>> [i for j in [[a[t:t+n] for x in a[:1:t+1] if (t%n)==False] for t in range(len(a))] for i in j] 
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15]] 
0

특정 경우에는 numpy 패키지를 사용하는 것이 유용 할 수 있습니다. 이 패키지에서 당신은 reshape 루틴을 가지고

import numpy as np 
x = np.array([1,2,3,4,5,6]) 
np.reshape(x, (-1,3)) 

그러나이 해결책이 아니다 패드 목록을, 그것은 N의 곱셈이 아니라면 것이다.

+0

Numpy는 이것에 대해 다소 과잉입니다. 그러나 주목할만한 기능에 대해 알고있는 것이 좋습니다. Joker5 감사합니다. –

2

혹시 boltons에 대해 들어 보셨습니까? 그것은 당신이 원하는 내장이라는 것을 가지고있는 표준 라이브러리

- 눈에 띄는에서 누락 아직 -

Boltons

같은 정신 등의 순수 파이썬 유틸리티의 집합입니다 chunked

from boltons import iterutils 

iterutils.chunked([1,2,3,4,5,6,7,8], 3) 

출력 :

[[1, 2, 3], [4, 5, 6], [7, 8]] 
메모리에 모든 것을 저장할 필요가 없습니다

그리고 무슨 boltons에서매력은 그것이 반복자chunked을 가지고있다가, chunked_iter을했다. 깔끔한, 그렇지?