2016-04-05 24 views
4

Python'a yeni geldim ve bir sözlüğü filtrelemenin "pythony" yöntemini formüle etmek için zor bir zaman geçirdim. böyleceBir sözlüğü birden çok değere göre filtreleme

'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0, ...} 
'660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0, ...} 

ve:

Şöyle bir sözlük var.

['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39', ...] 

Ne elde etmek istiyorum dizeleri listesindeki herhangi değerlerle sadece küpe var filtrelenmiş bir sözlüğü:

Sonra dizeleri bir listesi var. Tam olarak yapmayı başardı ettik ama bir gereği olarak yalnızca tek bir dize kullanarak ve şuna benzer: Ben kaldırırsanız, ancak

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if my_list[0] in v} 

[0] aşağıdaki hatayı alıyorum:

TypeError: unhashable türü: Gördüğünüz gibi

'115 : {'174': 4.0, '172': 4.0, '27': 3.0, '183': 5.0, '180': 3.0, '1039': 5.0, ... } 

'212' : {'4': 3.0, '473': 4.0, '208': 5.0, '123': 4.0, '476': 3.0, '474': 4.0, ...} 

, birinci başlığın üçüncü değer my_list içinde olan o '27' vardır: 'liste' İşte bazı beklenen çıkış değerleridir. İkinci tuple'daki ilk değer, my_list'de de bulunan '4' değerine sahiptir.

Bu konuda her türlü yardımı çok isterim.

Teşekkür ederiz! i Sorunuzu doğru anlamak

+0

Beklenen bazı çıktı değerlerini eklemelisiniz .. – msvalkon

+0

'... eğer my_list [0] in v öğesinde ilk öğe v ise .. belki de yapmak istediğiniz şey ... öğe için my_list öğesinde v içinde? –

cevap

4

bir kullanabilir v anahtarlarında x x in v.keys() kontrol eşittir denetler mylist elemanı in iç sözlük v olup MyList ve çekler yineleme halinde değer kümesinden ayrık değilse çiftleri tutarak ayarlayın: paylaştıkları yoksa

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'} 

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)} 

onlar sadece ayrık olacak en az bir eleman:

In [6]: st ={1,2,3} 

In [7]: v = [1,4,5] 

In [8]: st.isdisjoint(v) 
Out[8]: False 

In [11]: v = [7,4,5] 

In [12]: st.isdisjoint(v) 
Out[12]: True 
v dan any eleman kümesinde ise

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'} 

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if any(val in st for val in v)} 

biz elemanlarını tutmak Nerede:

O biraz eşdeğerdir.

En kötü durum biz mylist elemanları yinelemek x v ise kontrol, sette karşı len(v) elemanlarını kontrol her vaka için O(len(my_list)) ve aynı zamanda v bir maç olsun her zaman eşleştirme, aynı k yaratır.

bir listeye göre çiftleri daha maç tuşlarıyla bir dicti ekleyip eklerseniz, ne olacağını görebilirsiniz: 7 maçları vardır

In [22]: my_list = ['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'] 

In [23]: my_dict = {'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0}, 
    ....:   '660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0}, 
    ....:   '661': {'2': 4.0, '4': 3.0, '29': 5.0, '17': 4.0, '39': 4.0, '541': 3.0, '27': 1.0, '210': 4.0}} 


In [24]: print [(k,v) for k,v in my_dict.iteritems() for x in my_list if x in v] 
[('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('660', {'797': 4.0, '27': 1.0, '541': 3.0, '210': 4.0, '176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0})] 

Çünkü biz aynı eşleştirme yedi kez olsun, sen bir dict içinde dupes almazsınız ancak len (my_list) zamanlarını yinelemeniz ve x in v Eşleşme zamanının eşleşme uzunluğunu oluşturmalısınız. My_list'in uzunluğu büyüdükçe çalışma süresi de buna göre artacaktır.

Sadece hatırı sayılır bir fark var 1000 öğe my_list yapma: Başlamadan bir dizi kullanırsanız hemen hepsi o zaman set oluşturulmasında harcanan

In [35]: len(my_list) 
Out[35]: 1000 

In [36]: %%timeit 
    ....: st = set(my_list) 
    ....: {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)} 
    ....: 
10000 loops, best of 3: 21.9 µs per loop 
In [37]: timeit {k:v for k,v in my_dict.iteritems() for x in my_list if x in v} 
10000 loops, best of 3: 136 µs per loop 

o ishal daha hızlı 100 kez:

In [40]: timeit {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)} 

1000000 loops, best of 3: 1.09 µs per loop 
+0

listesi için iç içe döngü Her ikisi de önerileriniz harika çalıştı görünüyor. Her ne kadar belki de haifzhans çözümünün benim için daha kolay olduğunu düşünüyorum! –

+0

@Super_Soet, Farkın ne olduğunu tam olarak anladığını sanmıyorum, neden gördüğüm setin –

+0

Aha'yı kullanmam gerektiğini yanıtla ilgili bir örnek ekledim. Bu nedenle öneriniz, en kısa zamanda bulduğu andaki anahtarda daha fazla değer aramayı durdurur. Haifzhans önerisi, bir eşleşme bulmuş olmasına rağmen listenin geri kalanı boyunca arama yapmaya devam ederken, ilk maçtan sonra her türlü kontrolü gereksiz kılıyor? Doğru anladım mı? –

3

, listeyi mylist çapraz ve sözlüğün değerlerle her eleman karşılaştırmak gerekir mydict

{k:v for k,v in mydict.iteritems() for x in mylist if x in v}

1) k: k v, mydict.iteritems v() sözlük çiftini çift olarak yinelemek. mylist içinde x

2) v zaman x x in v

+0

İlk, ikinci, üçüncü vb. Bir eşleşme elde edip etmediğinize bakılmaksızın her bir öğeyi mandist'ten kontrol edersiniz, bu da aynı k/v eşleşme sürelerini 'x in v 'True olarak yarattığınız anlamına gelir. –

+0

@PadraicCunningham yes. Bu dict ve liste – haifzhan

İlgili konular