2009-10-07 10 views
1
biglist = 

[ 

    {'title':'U2 Band','link':'u2.com'}, 
    {'title':'ABC Station','link':'abc.com'}, 
    {'title':'Live Concert by U2','link':'u2.com'} 

] 

"u2.com"이 중복되어 목록의 세 번째 요소를 제거하고 싶습니다. 중복 "링크"요소를 원하지 않습니다. 그것은이 결과 수 있도록이 작업을 수행 할 수있는 가장 효율적인 코드 란 :목록에서 이러한 중복 파일을 제거하는 방법 (파이썬)

biglist = 

[ 

    {'title':'U2','link':'u2.com'}, 
    {'title':'ABC','link':'abc.com'} 
] 

내가 사용하는 등 많은 방법을 시도 많은 중첩 "... 대한의 ..."그러나 이것은 매우 비효율적이며, 너무 오래.

답변

2

:

그럼 당신은 다시이 같은리스트에 요소를 얻을 수 있습니다 과 같이, (파이썬 관용구 그대로 또는 오히려, 제거 중복으로 새로운 목록을 작성) :

# sort the list using the 'link' item as the sort key 
biglist.sort(key=lambda elt: elt['link']) 

newbiglist = [] 
for item in biglist: 
    if newbiglist == [] or item['link'] != newbiglist[-1]['link']: 
     newbiglist.append(item) 

이 코드는 "어떤 그룹에 대한 당신의 첫 번째 요소 (원래 biglist 상대 순서를) 줄 것이다 중복 ". 파이썬에서 사용하는 .sort() 알고리즘은 안정적인 정렬이 보장되어 있기 때문에 사실입니다. 즉, 동일한 (이 경우 link 인 요소) 동일한 것으로 결정된 요소의 순서는 변경되지 않습니다.

+1

나는이 접근법을 좋아합니다. 내가 할 수있는 한 가지 방법은 빅리스트를 제자리에 정렬하는 대신 정렬 된 항목 (biglist, key = lambda elt : elt [ 'link'])'을 사용하는 것입니다. biglist를 복사하기 때문에 (일시적으로) 더 많은 메모리를 사용하지만, 응용 프로그램에 따라 큰 데이터 객체를 변경하려고하지 않을 수도 있습니다. –

+0

그래, 좋은 지적이야. – dcrosta

+0

루프 안에서'newbiglist == []'를 제거하면 멋진 스피드 업을 얻을 수 있습니다. 어떻게 그걸 없앨 수 있니? 단순히 newbiglist를'newbiglist = [biglist [0]]'로 초기화하면'newbiglist [-1]'이 참조 할 수있는 것이 항상 있다는 것을 알 것입니다. – steveha

3

'u2.com'및 'abc.com'을 키로 사용하고 목록 요소를 값으로 사용하여 새 사전을 만듭니다. 사전은 고유성을 시행합니다. 이런 식으로 뭔가 :

uniquelist = dict((element['link'], element) for element in reversed(biglist)) 

(반전 된 목록의 첫 번째 요소는 사전에 남아있는 사람이 될 수 있도록 당신이 그것을 밖으로 가지고가는 경우에, 당신은 대신 마지막 요소를 얻을 것이다.). 다음 번 목록을 반복 및 중복 제거, 정렬 키 각 사전의 link 필드를 사용하여, 당신은 목록을 정렬 할 수 있습니다

biglist = uniquelist.values() 
+0

을 당신은 괄호의 추가, 불필요한 쌍의이 - DICT에 괄호()를하는 충분, 당신은 발전기를 소개하는 또 다른 세트가 필요하지 않습니다 표현. 또한 튜플 주위에 * 괄호가 필요하지는 않지만 아마 좋은 생각 일 것입니다. –

+0

BTW, +1 'dict'사용. (iterable뿐만 아니라) 실제 목록을 가지고 있다고 가정하면'reversed()'는 O (1)이어야하고'dict'은 O (n)이어야하며 값 추출은 O (n)이어야합니다. 그래서 이것이 가장 빠른 방법 인 것처럼 보입니다. 특히 큰 목록의 경우 더욱 그렇습니다. –

+0

스크래치 그. 리스트의'reversed()'는 복사 (최소한 Python 2.x에서) 때문에 O (n)이됩니다. 전반적인 성능은 O (n)이어야하지만 목록을 정렬하는 것보다 빠를 것 같습니다. –

1
biglist = \ 
[ 
    {'title':'U2 Band','link':'u2.com'}, 
    {'title':'ABC Station','link':'abc.com'}, 
    {'title':'Live Concert by U2','link':'u2.com'} 
] 

def dedupe(lst): 
    d = {} 
    for x in lst: 
     link = x["link"] 
     if link in d: 
      continue 
     d[link] = x 
    return d.values() 

lst = dedupe(biglist) 

dedupe()는 중복 된 것 중 첫 번째를 유지합니다.

biglist = [ 
    {'title':'U2 Band','link':'u2.com'}, 
    {'title':'ABC Station','link':'abc.com'}, 
    {'title':'Live Concert by U2','link':'u2.com'} 
] 

known_links = set() 
newlist = [] 

for d in biglist: 
    link = d['link'] 
    if link in known_links: continue 
    newlist.append(d) 
    known_links.add(link) 

biglist[:] = newlist 
+0

이것은 Ian Clelland의 대답과 거의 동일합니다. 단, 목록을 먼저 뒤집지 않는 것이 다릅니다. 역순으로 저장하는 것이 빠르지 만 모든 요소에 대해'link in d' 테스트를하는 것은 단순히 덮어 쓰는 것보다 느릴 수있는 것처럼 보입니다. 어쨌든, 속도 차이는 아마 소음에서 잃어 버리게된다. 그래서 그것은 당신이 좋아하는 스타일에 정말로 달려있다. –

+1

'link in d' 테스트는 사전이 해시 된 검색을 사용하기 때문에 빠릅니다. 그러면 정렬을 피할 수 있습니다. 그러나 가장 중요한 점은이 접근 방식이 덜 까다 롭고 확장하기 쉽다는 것입니다. 때때로 당신이 * 속 *의 첫 모습을 원하고 때로는 나중에 나타나는 것을 원한다면 어떻게 될까요? 이걸로 논리를 추가하는 것은 사소한 일입니다. Ian Clelland의 버전이 아닙니다. – steveha

+0

흠, 내가 너무 급하게 이야기했다고 생각해. Ian Clelland의 버전은 이전 버전이나 이후 버전을 유지할 수 있도록 쉽게 수정할 수 있다고 생각합니다. 그래서 그것은 정말로 당신이 선호하는 스타일에 달려 있습니다. – steveha

8

정말 큰 목록에 대한 가장 빠른 방법은, 다음입니다 ... link에 의해, 그리고 당신이 원한다면 중복 제거.

from collections import defaultdict 

nodupes = defaultdict(list) 
for d in biglist: 
    nodupes[d['url']].append(d['title'] 

이것은 당신에게 줄 것이다 :

defaultdict(<type 'list'>, {'abc.com': ['ABC Station'], 'u2.com': ['U2 Band', 
'Live Concert by U2']}) 
+1

마지막 줄의 목적은 무엇인가? 'biglist [:] = newlist'? 이상하게 보일지라도 보통'a = b [:]'는 목록 – dbr

+3

@dbr을 딥 카피하기 위해 수행되며'barename = whatever'은'barename'을 재 바인드합니다. 그러나'barename'에 대한 다른 참조가 있다면 참조하는 데 사용, 그들은 영향을 미치지 않습니다. 따라서이 경우 ** 요청에 따라 ** "목록에서 중복을 제거하지"않을 것입니다 : 중복이없는 _new_ 목록 개체를 만들지 만 이전 목록은 중복 목록으로 채 웁니다 (다른 목록이 있으면 물론 그 목록 객체를 유지하는 참조). 'somelist [:] = 뭐든간에 ** 완전 ** ** : **이 ** 문장은 목록 객체 자체의 본문을 변경합니다. 즉, ** "** 목록에서 중복을 제거합니다 **"입니다! –

+2

안정되어 있기 때문에 나는 이것을 좋아한다. 반환 된 항목은 원래 목록에 나타난 순서와 같을 것이다. 이는 일부 어플리케이션에서 중요합니다. –

0

당신은 그룹 항목에 defaultdict을 사용할 수 있습니다 : 당신이 남아있는 항목의 정확한 순서를 유지하려면 아마

관련 문제