2013-03-22 30 views
5

Python'un bunu yapması için yerleşik olması gerektiğini düşünüyorum. Öğelerin listesini alın ve söz konusu tuşa sahip öğelerin listesini ortak bir sözlük listesi haline getirin.Öğeleri bir anahtarla gruplama?

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

Ama bu yerleşik bir fonksiyonu iyi olurdu bir kullanma durumu yeterli sıklıkta geçerli:

Bunu yapmak kolay yeter. Ben gibi, kendim uygulamak olabilir: Bu işlem birkaç önemli yollardan itertools.groupby farklıdır

def grouped(iterable, key): 
    result = {} 
    for item in iterable: 
     result.setdefault(key(item), []).append(item) 
    return result 

lookup = grouped(items, key) 

. groupby aynı sonucu almak için, biraz çirkin olan bunu yapmak zorundayız:

lookup = dict((k, list(v)) for k, v in groupby(sorted(items, key=key), key)) 

Bazı örnekler:

>>> items = range(10) 
>>> grouped(items, lambda x: x % 2) 
{0: [0, 2, 4, 6, 8], 1: [1, 3, 5, 7, 9]} 

>>> items = 'hello stack overflow how are you'.split() 
>>> grouped(items, len) 
{8: ['overflow'], 3: ['how', 'are', 'you'], 5: ['hello', 'stack']} 

daha iyi bir yolu var mı?

+1

Bunun nasıl "bir kullanım durumu yeterince sık" olduğunu göremiyorum. Ben nadiren kullanırım ve kullanmam gerektiğinde, bir 'defaultdict' kullanmak sadece mükemmeldir. AFAIK, kendi başına istediğini yapan herhangi bir yerleşik değildir. – Bakuriu

+0

Muhtemelen haklısınız, ama bir parçam bunun bir grup oyuncağı kadar geçerli olduğunu düşünüyor. – FogleBird

cevap

3

Ayrıca bu soruyu comp.lang.python'a da gönderdim ve fikir birliği, yerleşik bir işlevi gerektirecek kadar yaygın olmayan bir şey gibi görünüyor. Yani, açık yaklaşımları kullanmak en iyisidir. Çalışırlar ve okunabilirler.

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

Sorumu silmeye gidiyordu, ama ben de burada bu terk edebilir durumda herkes bilgi arayan buna rastlar. Eğer groupby kabaca aynı API ile şey istediğimizde

+1

Yukarıdakilerle aynı işlevi yerine getirme, ancak "groupby" ile aynı API'yi kullanma şeklini nasıl elde edebileceğinizle ilgili cevabımı aşağıdan bakın. – tobych

1

şunu kullanabilirsiniz:

def groupby2(iterable, keyfunc): 
    lookup = collections.defaultdict(list) 
    for item in iterable: 
     lookup[keyfunc(item)].append(item) 
    return lookup.iteritems() 

Böylece arama tablosu size' ait iteritems dönen bir fonksiyonu haline yukarıdaki örnekle aynı, ama yapılan ve inşa edilmiştir.