2009-08-06 19 views
5

Yeni soru burada, lütfen benimle birlikte ol.Sözlük bir değer nasıl filtrelenir?

a = {"2323232838": ("first/dir", "hello.txt"), 
    "2323221383": ("second/dir", "foo.txt"), 
    "3434221": ("first/dir", "hello.txt"), 
    "32232334": ("first/dir", "hello.txt"), 
    "324234324": ("third/dir", "dog.txt")} 

başka sözlüğe taşınmasına birbirine eşit olduğu tüm değerleri istiyorum:

ı bir sözlük bu gibi bakarak var diyelim. peşin

remainder = {"2323221383": ("second/dir", "foo.txt"), 
      "324234324": ("third/dir", "dog.txt")} 

Teşekkür ve bir örnek sağlarsanız, mümkün olduğunca fazla yorum lütfen:

matched = {"2323232838": ("first/dir", "hello.txt"), 
      "3434221": ("first/dir", "hello.txt"), 
      "32232334": ("first/dir", "hello.txt")} 

Ve kalan eşsiz öğeleri bu gibi bakarak edilmelidir. Bir sözlükte üzerinde

+0

Diğerlerinin dediği gibi, örneklerinizi verdiğiniz gibi yalnızca sözlüklere sahip olamazsınız. Unique_id, dir ve dosya için birden fazla değeriniz var ve bu sadece yasal değil. Sözlük tuşları benzersizdir. –

+0

OH! Kötü, bunun için üzgünüm, düzelteceğim. –

+0

Artık düzeltmeniz Python'u sözdizimsel olarak doğru değil. Belki de "Aşağıdaki verileri Python veri yapılarında nasıl temsil edebilirim?" Diye sorabilirsiniz. ve sonra verilerinizi açıklayın. –

cevap

1

yineleme Python liste üzerinde yineleme farksız: Bu sözlüğün anahtarları ve tüm değerlerini yazdırır

for key in dic: 
    print("dic[%s] = %s" % (key, dic[key])) 

.

+0

Haklısınız, bu yorumlarda ele alındı ​​ve sorunun cevabını vermedi. – Triptych

1

Benzersiz kimliğinizin anahtar olacağını düşünüyorum.
Muhtemelen çok güzel değil ama benzersiz değerlere sahip bir dicti döndürür: ben size yayınını güncelledi gördüğüm

>>> dict_ = {'1': ['first/dir', 'hello.txt'], 
'3': ['first/dir', 'foo.txt'], 
'2': ['second/dir', 'foo.txt'], 
'4': ['second/dir', 'foo.txt']} 
>>> dict((v[0]+v[1],k) for k,v in dict_.iteritems()) 
{'second/dir/foo.txt': '4', 'first/dir/hello.txt': '1', 'first/dir/foo.txt': '3'} 

:

>>> a 
{'324234324': ('third/dir', 'dog.txt'), 
'2323221383': ('second/dir', 'foo.txt'), 
'3434221': ('first/dir', 'hello.txt'), 
'2323232838': ('first/dir', 'hello.txt'), 
'32232334': ('first/dir', 'hello.txt')} 
>>> dict((v[0]+"/"+v[1],k) for k,v in a.iteritems()) 
{'second/dir/foo.txt': '2323221383', 
'first/dir/hello.txt': '32232334', 
'third/dir/dog.txt': '324234324'} 
+0

, OP'nin istediği bu değildi. – SilentGhost

+0

Sizinki de değil. OP, başlangıçta kafamı karıştıran farklı bir versiyona sahipti. Tryptichs sürümü iyi görünüyor. – buster

10

kod aşağıda iki değişken, matches ve neden olacaktır remainders. matches, orijinal sözlüğün eşleşen öğelerinin karşılık gelen bir öğeye sahip olduğu bir dizi sözlüktir. remainder, örneğinizde olduğu gibi, tüm eşleşmeyen öğeleri içeren bir sözlük içerecektir.

Örneğinizde, eşleşen tek bir değerler kümesinin bulunduğunu unutmayın: ('first/dir', 'hello.txt'). Birden fazla set varsa, her biri matches'da karşılık gelen bir girişe sahip olacaktır.

import itertools 

# Original dict 
a = {"2323232838": ("first/dir", "hello.txt"), 
    "2323221383": ("second/dir", "foo.txt"), 
    "3434221": ("first/dir", "hello.txt"), 
    "32232334": ("first/dir", "hello.txt"), 
    "324234324": ("third/dir", "dog.txt")} 

# Convert dict to sorted list of items 
a = sorted(a.items(), key=lambda x:x[1]) 

# Group by value of tuple 
groups = itertools.groupby(a, key=lambda x:x[1]) 

# Pull out matching groups of items, and combine items 
# with no matches back into a single dictionary 
remainder = [] 
matched = [] 

for key, group in groups: 
    group = list(group) 
    if len(group) == 1: 
     remainder.append(group[0]) 
    else: 
     matched.append(dict(group)) 
else: 
    remainder = dict(remainder) 

Çıktı: Yeni başlayan

>>> matched 
[ 
    { 
    '3434221': ('first/dir', 'hello.txt'), 
    '2323232838': ('first/dir', 'hello.txt'), 
    '32232334': ('first/dir', 'hello.txt') 
    } 
] 

>>> remainder 
{ 
    '2323221383': ('second/dir', 'foo.txt'), 
    '324234324': ('third/dir', 'dog.txt') 
} 

, muhtemelen yukarıdaki kodda birkaç yabancı kavramlar tanıtılıyor ediyoruz.

sonra a
known_tuple = 'first/dir','hello.txt' 
b = {k:v for k, v in a.items() if v == known_tuple} 

olacaktı: Eğer filtre uygulamak istediğiniz değer verdiklerini biliyorum

+0

güzel. Şimdi cevabımla sorumu yanlış anladığımı görebiliyorum. Her neyse, bana iyi görünüyor :) – buster

+0

Teşekkür ederim, gruplar üzerinde okumam gerekecek, ama hepsi bir milyon, teşekkürler. Ayrıca sorumu düzenlediğiniz için teşekkürler! –

+0

Not, len (grup) 1, len (grup) == 1 okumalıdır. Kimlik testi ("is"), küçük tamsayı önbelleğe alma nedeniyle cPython'da burada çalışırken, içine girmek kötü bir alışkanlıktır. Eşitlik testi istiyorsun. –

0

: İşte bazı bağlantılar

a = dict(a.items() - b.items()) 

bu Py3k notasyondur, ama emin bir şeyim benzer eski sürümlerde uygulanabilir. known_tuple'un ne olduğunu bilmiyorsanız, önce bunu bulmanız gerekir. Böyle örneğin:

c = list(a.values()) 
for i in set(c): 
    c.remove(i) 
known_tuple = c[0] 
+0

Hayır, çok iyi olabilir "üçüncü/dir", "bir şey.txt", bilmiyorum. –

4

Ne soruyorsun bir "Ters İndeksi" denir - farklı ürün anahtarlarının bir listesi ile sadece bir kez kaydedilir.

>>> from collections import defaultdict 
>>> a = {"2323232838": ("first/dir", "hello.txt"), 
...  "2323221383": ("second/dir", "foo.txt"), 
...  "3434221": ("first/dir", "hello.txt"), 
...  "32232334": ("first/dir", "hello.txt"), 
...  "324234324": ("third/dir", "dog.txt")} 
>>> invert = defaultdict(list) 
>>> for key, value in a.items(): 
...  invert[value].append(key) 
... 
>>> invert 
defaultdict(<type 'list'>, {('first/dir', 'hello.txt'): ['3434221', '2323232838', '32232334'], ('second/dir', 'foo.txt'): ['2323221383'], ('third/dir', 'dog.txt'): ['324234324']}) 

Tersine çevirilen sözlükte 1 veya daha fazla tuşun bir listesiyle ilişkili orijinal değerler bulunur.

Şimdi, gözden geçirilmiş sözlüklerinizi bundan almak için.

Filtreleme:

>>> [ invert[multi] for multi in invert if len(invert[multi]) > 1 ] 
[['3434221', '2323232838', '32232334']] 
>>> [ invert[uni] for uni in invert if len(invert[uni]) == 1 ] 
[['2323221383'], ['324234324']] 

Benzer (ama daha basit) tedavi kez meydana öğeler için çalışır

>>> [ (i,multi) for multi in invert if len(invert[multi]) > 1 for i in invert[multi] ] 
[('3434221', ('first/dir', 'hello.txt')), ('2323232838', ('first/dir', 'hello.txt')), ('32232334', ('first/dir', 'hello.txt'))] 
>>> dict((i,multi) for multi in invert if len(invert[multi]) > 1 for i in invert[multi]) 
{'3434221': ('first/dir', 'hello.txt'), '2323232838': ('first/dir', 'hello.txt'), '32232334': ('first/dir', 'hello.txt')} 

genişletilmesi.

+0

Huh, çok basit, python standart lib kullanmak zorunda. daha fazlası, bunun için teşekkürler. –

+0

Ah, güzel de. Basit standart çağrılarla yapabileceğiniz şey inanılmaz :) – buster