2010-01-12 9 views
27

Çoktan çoğa korelasyonlu bir grup tuple gidiyorum, ve her b (a, b) 'nin b'ye karşılık gelen bütün harflerin bir listesine sahip olduğu bir sözlük yapmak istiyorum. Sözlükteki anahtar b'deki bir listeyi sınamak, sonra bir a aramak, sonra zaten yok ise, her seferinde tuple sindirim döngüsü boyunca ekleme yapmak garip görünüyor; ama henüz daha iyi bir yol bulamadım. Biri var mı? Bunu yapmanın başka bir yolu var mı daha güzel?Bir liste oluşturmanın veya zaten var ise ona ekleme yapmanın etkili yolu?

+1

kullanabilirsiniz veya algoritmik olarak? –

cevap

36

setdefault() yöntemi için the docs bakınız:

setDefault (anahtar [varsayılan])
anahtar değerini geri, sözlükte değilse. Değilse, anahtarı varsayılan değerine ekleyin ve varsayılanı döndürün. Varsayılan varsayılanı Yok'dur.

Bunu mevcut veya zaten mevcut değilse boş bir listeye b ayarlarsanız b alacak tek bir çağrı olarak kullanabilirsiniz - ve ya bir şekilde, dönüş b:

>>> key = 'b' 
>>> val = 'a' 
>>> print d 
{} 
>>> d.setdefault(key, []).append(val) 
>>> print d 
{'b': ['a']} 
>>> d.setdefault(key, []).append('zee') 
>>> print d 
{'b': ['a', 'zee']} 

üç hatlarında peşinde olduğun kontrol "değil" basit bir ile birleştirin ve yaptığın:

>>> b = d.setdefault('b', []) 
>>> if val not in b: 
... b.append(val) 
... 
>>> print d 
{'b': ['a', 'zee', 'c']} 
+3

'defaultdict', Python 2.5 veya üstü olduğunu varsayarak, 'setdefault''dan biraz daha güzel. – ephemient

+1

2.34 ile sıkışıp kaldım, bu yüzden bu benim için bir cevap - teşekkürler, James! – user249228

+5

D'oh. 'set()' güzel ama 2.4'e kadar yerleşik değil. Neden senin Python'un çok yaşlı? :-( – ephemient

2

Eğer tuples O sıralayabilirsiniz ardından sözlük O (n) oluşturmak (n log n)

veya simplier O (n) ama birçok dizilerini durumunda hafızasına ağır yük dayatabildiğinı:

your_dict = {} 
for (a,b) in your_list: 
    if b in your_dict: 
     your_dict[b].append(a) 
    else: 
     your_dict[b]=[a] 

Hmm, anlattığınız ile hemen hemen aynı. Bu garip olan ne?

Kirli işleri yapmak için bir sql veritabanı kullanmayı da düşünebilirsiniz.

+0

Daha basit bir yöntem, bu arada, O (n) 'dir, bu nedenle tuples yönteminizi sıralamak tercih edilir. – kennytm

+0

evet, düzenlenmiş sürümde de belirttim. –

+0

Reddetme hakkındaki yorumlarınız var mı? –

0

Sana önemli bir sınav çıkmak nasıl emin değilim, ama anahtar/değer çifti başlatıldı kez kolay :)

d = {} 
if 'b' not in d: 
    d['b'] = set() 
d['b'].add('a') 

seti sağlayacaktır sadece 1 'bir o 'koleksiyonda. Anahtar/değer bulunduğundan emin olmak için başlangıçtaki 'b' kontrolünü yapmanız gerekir.

+0

meraklı neden -1? bu bir şekilde yanlış mı? Cevabı yanlışsa sileceğim. –

15

gerçekten listelere bağlı değiliz varsayarsak, defaultdict ve set oldukça kullanışlıdır.

import collections 
d = collections.defaultdict(set) 
for a, b in mappings: 
    d[b].add(a) 

Eğer gerçekten yerine setleri listeleri istiyorsanız, bir

for k, v in d.iteritems(): 
    d[k] = list(v) 

ile bunu takip edebiliyoruz Ve gerçekten yerine defaultdict bir dicti isterseniz

söyleyebiliriz
d = dict(d) 

Gerçekten de, herhangi bir sebep görmüyorum.

+0

ah evet, bu, hiçbir şey için ilk kontrolün etrafında olur. Teşekkürler! Yeni bir şey öğrendim :) –

+1

+1, defaultdict' için, çünkü gerçekten en Pythonic çözümü. – jathanism

+1

Ben de nasıldı [bu adam bana varsayılanla gelmeme yardımcı oldu (lambda: defaultdict (list))] (http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html) – lkraav

4

Koleksiyonları kullanın.Bunun yerine bir if kullanmanın

your_dict = defaultdict(list) 
for (a,b) in your_list: 
    your_dict[b].append(a) 
+0

Kullanmak istemiyor musunuz? 'append'? – interjay

+0

Evet, bunu demek istedim. Teşekkürler –

+0

OP'in "o zaman zaten var değilse bir ekleme", orijinal listesinin filtrelenmesi gereken kopyalara sahip olabileceğini düşünmemi sağlıyor, bu yüzden "list" yerine "set" kullanıyorum. – ephemient

3

defaultdict AFAIK bu pythonic daha yerine try blok kullanmaktır.

your_list=[('a',1),('a',3),('b',1),('f',1),('a',2),('z',1)] 

your_dict={} 
for (a,b) in your_list: 
    try: 
     your_dict[b].append(a) 
    except KeyError: 
     your_dict[b]=[a] 

print your_dict 
0

Dict get yöntemi? Bu some_key sözlükte ise my_dict[some_key] değerini verir ve eğer değil - (aşağıdaki örnekte []) bazı varsayılan değeri döndürür:

my_dict[some_key] = my_dict.get(some_key, []).append(something_else) 
0

(sanki belki verimli değildir oldukça verimli olan başka yolu yok setleri) ve basit. Pratikte defaultdict'a benzer, ancak ek bir ithalat gerektirmez. Boş (Yok) tuşları ile bir zorunluluğunuz olduğunu varsayalım, bu aynı zamanda bir yerde dict tuşları yarattığınız anlamına gelir. Bunu dict.fromkeys yöntemiyle yapabilirsiniz ve bu yöntem ayrıca tüm tuşlara varsayılan bir değer koymaya izin verir. result olacak

keylist = ['key1', 'key2'] 
result = dict.fromkeys(keylist, []) 

: { 'key1': [], 'anahtar2': []}

Sonra döngü yapmak ve sözdizimsel demek güzel tarafından result['key1'].append(..) doğrudan

İlgili konular