2014-08-28 53 views
9

İki sözlük kataloğum var ve aralarındaki farkı bulmak istiyorum (yani, ilk listede var olan ancak ikincisi olmayanlar ve ikinci listede var olan ancak ilk listede olmayanlar).İki sözlük listesi arasındaki fark nasıl bulunur?

meselenin sözlüklerde

a = [{'a': '1'}, {'c': '2'}] 
b = [{'a': '1'}, {'b': '2'}] 

set(a) - set(b) 

Sonucu listesi olmasıdır

TypeError: unhashable type: 'dict' 

İstenilen Sonuç:

{'c': '2'} 

Bunu nasıl başarırız? Listede ise

+1

sözlükleriniz yalnızca tek öğelerdir? eğer öyleyse, listeyi tek bir sözlük haline getirmek daha mantıklı olmaz mı? – cmd

+0

nope, onlar çok sayıda öğe (yaklaşık 15 her biri büyük olasılıkla) ve bu her listede yaklaşık 3000 ila 1000 diktatörlerin bir listesi olacaktır – Chris

+0

İstediğiniz sonucu kontrol edebilir misiniz. Tanımınıza göre [simetrik bir farklılık] görüyorsunuz (http://en.wikipedia.org/wiki/Symmetric_difference) –

cevap

11

Sen görmek in operatörünü kullanabilirsiniz

a = [{'a': '1'}, {'c': '2'}] 
b = [{'a': '1'}, {'b': '2'}] 

>>> {'a':'1'} in a 
True 
>>> {'a':'1'} in b 
True 

>>> [i for i in a if i not in b] 
[{'c': '2'}] 
0

yapabilirsiniz ayrıca birlikte filter bir lambda:

:

her listede farklı öğeleri istiyorsanız

print filter(lambda x: x not in b,a) + filter(lambda x: x not in a,b) 

[{'c': '2'}, {'b': '2'}] 

Ya da sadece filter(lambda x: x not in b,a)a öğeleri alabiliriz, ancak içinde b 0 Eğer bellekte dicts tam listesini oluşturmak istemiyorsanızEğer kullanabilirsiniz itertools.ifilter

from itertools import ifilter 

diff = ifilter(lambda x: x not in b,a) 
Sonra sadece fark üzerinde yineleme

:

for uniq in diff: 
    print uniq 
3

Farkı bulmak istiyorum aralarında (yani ilk listede var ama ikinci değil ve ne neyi ilk listeyi) tanımına göre

ikinci listede var ama, bir Symmetric difference arayan:

>>> import itertools 

>>> a = [{'a': '1'}, {'c': '2'}] 
>>> b = [{'a': '1'}, {'b': '2'}] 
>>> intersec = [item for item in a if item in b] 
>>> sym_diff = [item for item in itertools.chain(a,b) if item not in intersec] 

>>> intersec 
[{'a': '1'}] 
>>> sym_diff 
[{'c': '2'}, {'b': '2'} 

Alternatif olarak (örneğinizde verilen plain difference'u kullanarak):

>>> a_minus_b = [item for item in a if item not in b] 
>>> b_minus_a = [item for item in b if item not in a] 
>>> sym_diff = list(itertools.chain(a_minus_b,b_minus_a)) 

>>> a_minus_b 
[{'c': '2'}] 
>>> b_minus_a 
[{'b': '2'}] 
>>> sym_diff 
[{'c': '2'}, {'b': '2'}] 
+0

Bu, cevaplardan birinde referans olarak verildi ancak OP'nin burada istediği şeyin tam olarak bu olduğuna inanıyorum. .so +1. One Question, 'itertools.chain' kullanmak yerine' + 'operatörünü' a_minis_b' ve 'b_minus_a''nı sym_diff'de birleştirmek için kullanamıyor musunuz? –

+1

@ KhalilAmmour- خليلعمور Evet yapabilirsin. Ama 'itertools.chain() 'yi kullanarak, kullanmadan önce sonuç listesini bellekte oluşturmanıza gerek yoktur. "Büyük" listeler için özellikle önemlidir. Bununla birlikte biraz daha tutarlı olmak için, burada bir liste kavraması yerine bir jeneratör kullanmalıyım: 'a_minus_b = (eğer bir öğede öge olmayan öğe için b)'.Ancak, bu kod, kullandığınız zaman öğeleri tükettiği için, bu örnek kodda daha da zor olacaktır. –

+0

Ahah ... Görüyorum ki ... ... bu bellek optimizasyonu içindi, bana jeneratörle bir örnek gösterebilir misiniz, eğer cevabınızı düzenleyerek olabilir, eğer yapacak mısın? –