2010-04-14 8 views
30

파이썬에서 재귀 목록 통합을 정의 할 수 있습니까?파이썬에서 재귀 목록을 이해합니까?

아마도 단순한 예를

만의 라인을 따라 뭔가 :이 가능한처럼 아무것도

nums = [1, 1, 2, 2, 3, 3, 4, 4] 
willThisWork = [x for x in nums if x not in self] # self being the current comprehension 

인가?

+4

'주문 (list (set (num))'에 문제가없는 경우. 그렇지 않으면 http://docs.python.org/library/itertools.html의 'unique_everseen'을 확인하십시오. – kennytm

+0

새는 추상화 경고. 비록 내 생각으로는 cpython에서 루프로 구현 될지도 모르지만 ......... – wim

답변

30

아니요, "현재 이해력"을 나타내는 (문서화 된, 견고한, 안정된, ...--) 방법이 없습니다. 당신은 루프를 사용할 수 있습니다 물론

res = [] 
for x in nums: 
    if x not in res: 
    res.append(x) 

이가 (O (N 제곱)) 매우 비용이 많이 드는, 그래서 당신은 보조 set (내가 있으리라 믿고있어으로 최적화 할 수 res에서 항목의 순서를 유지 nums에있는 항목의 합동, 그렇지 않으면 set(nums) 당신을 할 것이다; -) ... :

res = [] 
aux = set() 
for x in nums: 
    if x not in aux: 
    res.append(x) 
    aux.add(x) 

이 빠르고 매우 긴 목록 (O (N)에 대한 엄청난입니다 N 제곱 대신).

편집 : 파이썬 2.5 또는 2.6, vars()['_[1]'] 실제로 나는 문서화 더 가 없습니다 명확히하여 내 문을 자격을하는 이유 (비 중첩 listcomp에 대한) self에 대한 당신이 원하는 역할을 작동 할 수 있습니다, 견고하고 안정적인 "목록 작성 중"에 액세스하는 방법 - 고유 한, 문서화되지 않은 "이름"'_[1]' (의도적으로 올바른 식별자가 아닌 것으로 선택 ;-) "구현 아티팩트"및 그에 의존하는 모든 코드의 정점입니다 불행에서 벗어날 가치가있다 ;-). 당신이 nums에서 고유 요소의 목록을 만들려고처럼

+1

집합 연산을 통해 O (n log (n))가된다. 나는 꽤 확신한다. –

+2

파이썬에서 @ dash-tom-bang 세트는 (STL 에서처럼) 빨강 - 검정 나무로 구현되지 않지만 내가 아는 한 해시를 사용하므로 O (N)이됩니다. –

+1

@ Justin은 정확합니다 - python sets와 dicts는 O (1) 항목을 추가하기위한 상각 된 비용과 조회를위한 O (1) 비용으로 잘 최적화 된 해시입니다. –

2

no. 작동하지 않을 경우 목록 이해력이 실행되는 동안 참조 할 수있는 문자는 self입니다.

물론 주된 이유는이 용도로 설계되지 않은 목록 내포입니다. 이 당신이 원하는,하지만 당신은 중첩 된 지능형리스트 쓸 수있는 경우

1

확실하지 : 코드 예제에서

xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)] 
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]] 

을, 당신은 단순히 당신이 세트로 할 수있는 중복을 제거 할 것 :

xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4])) 
assert xs == [1, 2, 3, 4] 
1

번호

는하지만 보인다. nums의 항목이 해쉬해야

unique_items = set(nums) 

참고 :

당신은 set를 사용할 수 있습니다.

다음 작업을 수행 할 수도 있습니다. 내가 원래의 생각에 도달 할 수있는 것은 가까운 것입니다. 그러나 이것은 set을 생성하는 것만 큼 효율적이지 않습니다.

unique_items = [] 
for i in nums: 
    if i not in unique_items: 
     unique_items.append(i) 
2

이 작업을 수행 :

nums = [1, 1, 2, 2, 3, 3, 4, 4] 
set_of_nums = set(nums) 
unique_num_list = list(set_of_nums) 

또는이 : 사실 당신이 할 수있는

unique_num_list = sorted(set_of_nums) 
+0

목록의 내포는 불필요합니다. 'unique_num_list = list (set_of_nums)'입니다. 'sorted (set_of_nums)'는리스트를 반환합니다. –

+0

@PreludeAndFugue : 좋은 지적. 코드를 변경하겠습니다. – hughdbrown

8

을! 설명이있는이 예제는 잘 설명 할 것입니다.

숫자가 5 이상인 경우에만 숫자를 가져 오는 재귀 예제를 정의하고 그렇지 않은 경우 숫자를 증가시키고 '확인'함수를 다시 호출하십시오.

[5, 5, 5, 5, 5, 6] 
>>> 

본질적으로 두 익명 함수가 이러한 방식으로 상호 작용 :

let f(g,x) = { 
       expression, terminal condition 
       g(g,x), non-terminal condition 
      } 

let g(f,x) = { 
       expression, terminal condition 
       f(f,x), non-terminal condition 
      } 

메이크 g, F가되는 원점 복귀 5.

print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ] 

결과에 5에 도달 할 때까지이 과정을 반복 하나 또는 둘 모두에서 매개 변수가 수정되어 터미널 조건에 도달하도록 절을 추가 한 다음이 방법으로 f (g, x)가되는 이되는 것을 제외하면 '동일한'함수가됩니다. f의 복사본은 다음과 같습니다 :

f(g,x) = { 
       expression, terminal condition 
       { 
        expression, terminal condition, 
        g(g,x), non-terminal codition 
       }, non-terminal condition 
      } 

실행시 익명 함수 자체에 액세스 할 수 없기 때문에이 작업을 수행해야합니다.

(lambda f,v: somehow call the function again inside itself)(_,_) 

그래서 본 실시 예에서는 A = 제 함수와 B 제를 보자. 우리는 A를 B로, B를 A라고 부릅니다. 이제 B는 본질적으로 A의 복사본이고 전달 된 매개 변수이므로 A를 호출하는 것과 같은 B를 호출 할 수 있습니다.

이것은 다음과 같은 계승을 생성합니다. 목록

print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ] 

[1, 2, 6, 120, 720, 5040] 
>>> 
+2

람다 복제는 필요하지 않습니다. 당신은 어떤 종류의 두 번째 람다가 스스로 호출 할 수 있도록하는 첫 번째 람다로서 일반 프록시를 사용할 수 있습니다. '(lambda self, v : ...., firstvalue)'(λ f, arg : f (f, arg))' –

관련 문제