2013-08-21 7 views
4

나는이 두 배열 사이의 교차를 만드는 방법을 알고하지 않습니다파이썬 배열 교차로 효율적으로

a = [[125, 1], [193, 1], [288, 23]] 
b = [[108, 1], [288, 1], [193, 11]] 

result = [[288,24], [193, 12]] 

그래서 교회법 첫 번째 요소입니다, 배열의 두 번째 요소가 요약되어, 어떤 아이디어 방법 이것을 효율적으로하기 위해서?

좋아, 나는 효율적이라는 말의 의미를 설명하지 않은 실수를했다. 미안하다. 다음 순진한 구현을 고려해보십시오 :

a = [[125, 1], [193, 1], [288, 23]] 
b = [[108, 1], [288, 1], [193, 11]] 
result = {} 
for i, j in a: 
    for k, l in b: 
     if i == k: 
      result[i] = j + l 
print result 

그래서 나는 더 효율적인 방식으로 내 문제를 해결할 수있는 방법을 찾으려고 노력했습니다. 그래서 내가 네 도움이 필요 했어.

이 테스트 케이스를 사용해보십시오 (내 코드는에 있습니다) :

Test Case

상영 시간 : 28.6980509758

+0

두 개의 일치하는 요소가있는 경우 어떻게해야합니까? 그것들 역시 합쳐 져야할까요? 예 :'a = [[100, 1], [1002]]','b = [[50, 1]] – Brionius

+0

a와 b에는 뚜렷한 요소가 있습니다. a의 요소는 b에서 발생할 수 있습니다. – badc0re

+0

a 또는 b에서 중복 된 적이 없다는 말입니까? – Brionius

답변

3
result = [] 
ms, mb = (dict(a),dict(b)) if len(a)<len(b) else (dict(b),dict(a)) 
for k in ms: 
    if k in mb: 
    result.append([k,ms[k]+mb[k]]) 
+0

죄송합니다. 저는 마지막 문장에서 []를 놓쳤다는 것을 깨달았습니다. – FUD

+0

@ badc0re 당신이 이것을 호의적으로 벤치마킹 할 수 있겠습니까? – FUD

+0

배열이 정말 작고 단지 2 센트 인 데이터가있는 경우에 대비하여 좋은 최적화를 추가했습니다 – FUD

2

사용 카운터 :

c_sum = Counter() 
c_len = Counter() 
for elt in a: 
    c_sum[elt[0]] += elt[1] 
    c_len[elt[0]] += 1 

for elt in b: 
    c_sum[elt[0]] += elt[1] 
    c_len[elt[0]] += 1 

print [[k, c_sum[k]] for k, v in c_len.iteritems() if v > 1] 
2

여기 go

당신은 또한 목록에서 중복 항목을 원하는 그것을 계산하는 경우3210
a = [[125, 1], [193, 1], [288, 23]] 
b = [[108, 1], [288, 1], [193, 11]] 
for e in a: 
    for e2 in b: 
     if e[0] == e2[0]: 
      inter.append([e[0], e[1]+e2[1]]) 
print inter 

출력

[[193, 12], [288, 24]] 
+3

질문에서 '효율적으로'라는 단어를 놓친 것일까 요? O (n^2) 알고리즘이 적합하다고 생각하지 않습니다. –

+0

맞아, 맞아. 나는 그 비트를 놓쳤다. – mavili

+2

나는 OP가 버릇없이 "효율적으로"라는 단어를 사용했다고 생각합니다. 또는 무지. 그가 실제로 그것을 의미한다면, 그는 목록의 크기, 일반적인 시간 제약, 타이밍 정보로 시도한 다른 해결책, 그리고 다른 언어 대신에 파이썬을 사용하는 이유를 지정했을 것입니다. –

2

이 솔루션은 작동합니다.

from collections import defaultdict 

a = [[125, 1], [193, 1], [288, 23]] 
b = [[108, 1], [288, 1], [193, 11]] 

d = defaultdict(int) 

for value, num in a+b: 
    d[value] += num 
result = filter(lambda x:x[1]>1, d.items()) 
result = map(list, result) # If it's important that the result be a list of lists rather than a list of tuples 
print result 
# [[288, 24], [193, 12]] 
2

처음에는 파이썬에 배열이 없습니다. 그것은 목록이입니다. 이름의 문제지만 혼란 스러울 수 있습니다. 이에 대한 한 줄은 다음과 같습니다

[ [ae[0],ae[1]+be[1]] for be in b for ae in a if be[0] == ae[0] ] 

PS : 당신이 "교차로"를 말하는 것처럼, 나는 목록이 설정처럼 ("가방", 정말) 가정, 그것은, 가방, 그들은 제대로 정규화 (즉, 반복되는 요소/키가 없음).

result = [[k, da[k] + db[k]] for k in set(da.keys()).intersection(db.keys())] 

또는 파이썬 2.7에서 당신은 또한 단지 viewkeys을 사용할 수 있습니다 : 당신이 당신은 할 수처럼 일단 그것이 더 나은 사전

da = dict(a) 
db = dict(b) 

로 저장 될 것 같은

+1

하나의 라이너가 과대 평가되었습니다. 특히 비효율적입니다. – FUD

+1

이해가되면 중요한 부분이 있습니다. 퍼포먼스에 대해 너무 걱정한다면 파이썬으로 무엇을 개발하고 있습니까? 다른 언어와 비교할 때의 주된 장점은 표현이 아니라 성과입니다. 언어의 중요한 부분을 불신하고 사람들이 그것에 대해 알지 못하게하십시오. 그들 자신의 결론을 이끌어 내도록하십시오. 이 특별한 경우에는 성능 차이가별로 없다고 생각합니다. 시간 있니? –

+1

이것은 OP가 제기 한 질문에 답하지 못했습니다. 이것은 효율적이지 않습니다. 언어에 대해 논쟁을하는 것이 당신의 솔루션이 비효율적 인 알고리즘이라는 것을 경감 시키지는 못합니다. – cmd

4

이 데이터 보인다 세트 대신

result = [[k, da[k] + db[k]] for k in da.viewkeys() & db] 
+0

나는 downvoted하지 않았습니다, 귀하의 솔루션은 지금까지 0.0124080181122에서 계산 된 최고의 성능을 가지고 있습니다. – badc0re

+0

멋지다! pythonic and efficient – FUD

2

여기는 어떻게 접근 할 것인가? a와 b에 SS :

k = {} # store totals 
its = {} # store intersections 
for i in a + b: 
    if i[0] in k: 
     its[i[0]] = True 
     k[i[0]] += i[1] 
    else: 
     k[i[0]] = i[1] 
# then loop through intersections for results 
result = [[i, k[i]] for i in its] 
+0

또한 위대한 공연 (0.0174601078033)하지만 나는 그 [i [0]] = True 부분을 얻지 못합니다. – badc0re

+1

키/id를 두 번째로 치면 교차 된 것을 의미하고, 교차점을 찾기 위해 다른 루프를 수행하는 대신 저장합니다. – Faisal

2

내가 가지고 : O에서 실행

from collections import defaultdict 
d = defaultdict(list) 
for series in a, b: 
    for key, value in series: 
     d[key].append(value) 
result2 = [(key, sum(values)) for key, values in d.iteritems() if len(values) > 1] 

(LEN (A) + 렌 (B)), 또는 당신을위한 18.79 대 내 노트북에 약 0.02 초 . 또한 알고리즘에서 result.items()과 같은 결과를 반환했음을 확인했습니다.

1

이 솔루션은 가장 빠를 수는 없지만 가장 간단한 구현 일 수 있으므로 완벽하게 게시하기로했습니다. 당신은 단지 일반적인 키를 포함해야하는 경우

aa = Counter(dict(a)) 
bb = Counter(dict(b)) 
cc = aa + bb 
cc 
=> Counter({288: 24, 193: 12, 108: 1, 125: 1}) 

list(cc.items()) 
=> [(288, 24), (193, 12), (108, 1), (125, 1)] 

는 :

[ (k, cc[k]) for k in set(aa).intersection(bb) ] 
=> [(288, 24), (193, 12)] 
1

numpyserachsorted(), argsort()intersect1d() 가능한 대안과 매우 빠르게 할 수 있습니다. 이 예제는 고유하지 않은 첫 번째 요소 문제도 처리해야합니다.

>>> import numpy as np 
>>> a=np.array([[125, 1], [193, 1], [288, 23]]) 
>>> b=np.array([[108, 1], [288, 1], [193, 11]]) 
>>> aT=a.T 
>>> bT=b.T 
>>> aS=aT[0][np.argsort(aT[0])] 
>>> bS=bT[0][np.argsort(bT[0])] 
>>> i=np.intersect1d(aT[0], bT[0]) 
>>> cT=np.hstack((aT[:,np.searchsorted(aS, i)], bT[:,np.searchsorted(bS, i)])) 
>>> [[item,np.sum(cT[1,np.argwhere(cT[0]==item).flatten()])] for item in i] 
[[193, 12], [288, 24]] #not quite happy about this, can someone comes up with a vectorized way of doing it? 
+0

성능은'a' 및'b' 배열의 차원에 따라 다릅니다.이 게시물을 참조하십시오 : http://stackoverflow.com/questions/3650194/are-numpys-math-functions-faster-than-pythons –