2009-08-06 7 views
5

ここでの初心者の質問ですので、私にご負担ください。値で辞書をフィルタリングする方法は?

だが、私はこのように見ている辞書を持っているとしましょう:

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")} 

は私が互いに等しくなっているすべての値が別の辞書に移動することにしたいです。

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

、残りの比類のない項目は次のように見ている必要があります。

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

事前のおかげで、あなたは一例を提供する場合、可能な限り多くのコメントしてください。辞書を超える

+0

他の人が言っているように、あなたの例のように辞書を持つことはできません。あなたはunique_id、dir、fileという複数の値を持っていますが、それは合法ではありません。辞書キーは一意です。 –

+0

OH!私の悪い、それについて申し訳ありません、私はそれを修正します。 –

+0

あなたの修正は、構文上正しいPythonではありません。おそらく、「次のデータをPythonのデータ構造で表現するにはどうすればよいですか?あなたのデータを記述します。 –

答えて

1

反復処理はPythonでリストを反復処理と違いはありません:

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

これはあなたの辞書のキーと値のすべてを印刷します。

+0

あなたが正しい間に、これはコメントで処理され、彼の質問に答えることはできませんでした。 – Triptych

1

あなたの一意のIDが鍵であると仮定します。
おそらくない非常に美しいが、あなたのユニークな値を持つ辞書を返します。私はあなたのポストを更新見てきました

>>> 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が要請したことではありません。 – SilentGhost

+0

あなたもそうではありません。 OPには、私を混乱させる最初のいくつかの異なるバージョンがありました。 Tryptichsのバージョンは問題ありません。 – buster

10

以下のコードは、2つの変数matchesになりますし、 remaindersmatchesは、辞書の配列であり、元の辞書の一致する項目に対応する要素があります。 remainderは、あなたの例のように、すべての不一致項目を含む辞書を含みます。

この例では、一致する値のセットは1つだけです:('first/dir', 'hello.txt')です。複数のセットがある場合は、それぞれに対応するエントリがmatchesにあります。

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) 

出力:初心者として

>>> 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') 
} 

は、おそらく上記のコードでは、いくつかのなじみのない概念を導入されています。ここではいくつかのリンクです:

+0

nice。私は今私の答えで質問を誤解しているのを見ることができます。 とにかく、私によく見えます:) – buster

+0

ありがとう、私はグループを読み上げる必要がありますが、それはすべての良い、ありがとう、百万です。私の質問を編集してくれてありがとう! –

+0

len(group)は1である必要があります。len(group)== 1。cPythonでは小数点のキャッシングが原因でアイデンティティテスト(「is」)が機能しますが、これは悪い習慣です。あなたは平等テストが必要です。 –

0

あなたがフィルタリングしたいどのような値を知っていれば:

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

その後、aになるでしょう:

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

これはpy3k表記ですが、私は何かを確信していますレガシーバージョンでも同様のことが実現できます。 known_tupleが何であるかわからない場合は、まずそれを見つけ出す必要があります。たとえば、次のように:

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

いいえ、それは "third/dir"、 "something.txt"になる可能性があります。わかりません。 –

4

「転置インデックス」何を求めていると呼ばれている - 明確な項目は、キーのリストを一度だけ記録されています。

>>> 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']}) 

逆辞書には、1つ以上のキーのリストに関連付けられた元の値があります。

ここから改訂辞書を入手してください。

フィルタリング:

>>> [ 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']] 

が一度発生アイテムの類似の(しかし、より簡単な)治療作品

>>> [ (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')} 

拡大。

+0

ああ、非常に単純な、Python標準のlibを使用する必要があります。もっと、ありがとう。 –

+0

ああ、いいですね。 シンプルな標準コールでできることは素晴らしいです:) – buster

関連する問題