2017-12-05 6 views
-1

수백만 개의 항목이있는 사전 목록이 있습니다. 목록에서 동일한 키 이름이없는 고유 항목 만 추출하려는 경우 스레드 또는 병렬 검사를 사용하는 빠른 방법이 있습니다. 대신 순차적Python에서 고유 한 목록 항목 가져 오기

주 아래로 내 코드 : 내 목록이 사전의 목록입니다 각 사전이 서로 다른 키를 가지고 있지만 그들은 키 [ '이름']의 동일한 값을 가질 수도가 일치하는 경우에, 나는 단지해야 하나

예 :

lst = [{ 'name': 'x', 'bar': 1, 'foo': 2}, { 'name', 'zoo', 'foo': 3, 'bar' 5}, { 'name': x ','bar ': 33,'foo ': 10}] 여기 두 개의 사전이 같은 이름을 갖습니다. 새 목록에 하나만 저장합니다. new_lst = [{ 'name': 'x', 'bar': 1, 'foo': 2}, { 'name', 'z', 'foo': 3, 'bar '5}] 당신이 예제를 제공하지 않았기 때문에

new_lst = [] 
for x in lst: 
    flag = False 
    for n in new_lst: 
      if x['name'] == n['name']: 
        flag = True 
        break 
    if not flag: 
     new_lst.append(x) 
+1

이러한 유형의 문제에 대해 집합을 사용할 수 있습니다. https://docs.python.org/2/library/sets.html – Laurijssen

+1

항목을 '이름'으로 사전에 복사합니다. –

+0

[count] (https://www.programiz.com/python-programming/methods/list/count) –

답변

0

, 정확하게 당신이 원하는 것을 포착하기 어려운,하지만 당신은 찾을 수있는 다음과 같은 흥미로운 : 여기 제안하고 무엇

a = [{'bar': 1, 'foo': 2}, {'foobar': 3, 'bar': 5}] 

a = {k: v for subdict in a for k, v in subdict.items()} 
print(a) # {'bar': 5, 'foo': 2, 'foobar': 3} 
#   ^'bar' appears only once (but value could be either 1 or 5) 
#     ^'foobar' is taken from the 1st dict. Does not exist in 2nd. 
#        ^'foo' is taken from the 2nd dict. Does not exist in 1st. 

list으로 줄이고 하나는 dict으로 줄입니다. 중복 된 내용은 자동으로 덮어 쓰여질 수 있으므로 (순서를 보장 할 수 없음) 자동으로 수행됩니다.


또는 다음 (간단 인 이해하는)와 같은을 달성 할 수 :

res = a[0] 
for d in a[1:]: 
    res.update(d) # every dict is <<applied>> to the previous one as an update. 
print(res) # {'bar': 5, 'foo': 2, 'foobar': 3} 


참고

내 솔루션은 위의 가정 dict -01-01을 보존하는 데 신경 쓰지 않아도됩니다.스키마.

+0

목록은 아래와 같습니다. a = [{ 'name': 'x' 'bar': 3, 'bar': 5}, { 'name': x ','bar ': 33,'bar ': 1,'foo ': 2} 'foo': 10}] 사전을 병합하고 싶지 않습니다. 두 개의 사전에 같은 이름의 동등한 x가 있으므로 새 목록에 하나만 저장합니다. new_lst = [{ 'name': 'x', ' '% 1', 'foo': 2}, { 'name', 'z', 'foobar': 3, 'bar': 5}] – Amr

1

재현 예 : 나는

다음 : 그 일의

import string 
import random 
lst = [] 
for i in range(10000): 
    lst.append({'name':random.choice(string.letters)+random.choice(string.letters), 
       'foo':random.choice(range(100)), 
       'bar':random.choice(range(100))}) 

길 : 큰 DICT 좋은 벤치 마크를 계산하는

그래서 나는 reprocible 예제를 빌드 함수에서 길을 컴파일 :

def your_fun(lst): 
    new_lst = [] 
    for x in lst: 
     flag = False 
     for n in new_lst: 
       if x['name'] == n['name']: 
         flag = True 
         break 
     if not flag: 
      new_lst.append(x) 
    return(new_lst) 

더 빠른 방법 :

는 루프의 수를 limitate하기위한 빠른 방법 이미 목록에서 본 이름을 저장하여 (루프 감속이다).

def my_fun(lst): 
    new_lst = [] 
    seens_names = [] 
    for x in lst: 
     if not x['name'] in seens_names: 
      new_lst.append(x) 
      seens_names.append(x['name']) 
    return(new_lst) 

벤치 마크 :

내가 벤치 마크를 수행

%timeit your_fun(lst) 
1 loop, best of 3: 1.14 s per loop 


%timeit my_fun(lst) 
10 loops, best of 3: 143 ms per loop 

그래서 하나 개의 루프를 억누르고함으로써, (10)에 의해 시간 비용을 분할 할 수 있습니다를 ...

결론 :

멀티 스레딩을 고려하기 전에 가능한 한 많은 루프를 피하면 코드가 더 빨라질 것입니다.

성능을 계속 유지하는 다른 방법이있을 수 있습니다.

멀티 스레드를 조사하기 전에 또 다른 개선점은 cython에서이 작업을 코딩하는 것입니다.

+0

감사합니다. 표시된 이름에 대해 목록 대신 dict를 사용하여 메서드 아래에서 가장 빨리 찾을 수 있습니다. new_dct = {} for i, x in 열거 형 (lst) : new_dct.get (x [ 'name']) : new_dct [x [ 'name']] = x – Amr