6

SO に関するトピックに関する多くの質問が証明しているように、辞書の一部を取得することはかなり一般的なタスクであり、かなり優れた解決策があります。

{k:v for k,v in dict.viewitems() if some_test(k,v)}

しかし、それは独自のマッピングを持つ新しい辞書を作成します。多くの操作では、元の dict の不変ビューがあれば便利です (つまり、ビューでの割り当てまたは削除操作はサポートされません)。このような型を実装するのはおそらく簡単ですが、ローカル ユーティリティ クラスが急増するのは良くありません。

だから、私の質問は次のとおりです。そのような「サブセットビュー」を取得する組み込みの方法はありますか? または、そのようなユーティリティの適切な実装を提供するサードパーティのライブラリ (できれば PyPi 経由で利用可能) はありますか?

4

3 に答える 3

6

ディクショナリへのビューを取得する組み込みの方法はないようです。最も簡単な回避策は、Jochen のアプローチのようです。私の目的に合わせて彼のコードを少し調整しました。

from collections import MutableMapping

class DictView(MutableMapping):
    def __init__(self, source, valid_keys):
        self.source, self.valid_keys = source, valid_keys

    def __getitem__(self, key):
        if key in self.valid_keys:
            return self.source[key]
        else:
            raise KeyError(key)

    def __len__(self):
        return len(self.valid_keys)

    def __iter__(self):
        for key in self.valid_keys:
            yield key

    def __setitem__(self, key, value):
        if key in self.valid_keys:
            self.source[key] = value
        else:
            raise KeyError(key)

    def __delitem__(self, key):
        self.valid_keys.remove(key)

d = dict(a=1, b=2, c=3)
valid_keys = ['a', 'c']
d2 = DictView(d, valid_keys)
d2['a'] = -1  # overwrite element 'a' in source dictionary
print d  # prints {'a': -1, 'c': 3, 'b': 2}

そのため、方法d2が異なるため、印刷以外のすべての面で辞書のように動作し__repr__()ます。dictからget に継承するに__repr__()は、 の場合と同様に、すべてのメソッドを再実装する必要がありcollections.OrderedDictます。読み取り専用ビューのみが必要な場合は、 および の実装を継承してcollections.Mapping保存できます。パラメータを選択してコンパクトな形式で渡すと便利です。__setitem__()__delitem__()DictViewself.__dict__

于 2012-07-19T11:50:40.313 に答える
4

これは非常に簡単に実装できます。

from collections import Mapping
class FilteredItems(Mapping):
    def __init__(self, source, filter):
        self.source = source
        self.p = filter

    def __getitem__(self, key):
        x = self.source[key]
        if self.p(key,x):
            return key,x
        else:
            raise KeyError(key)


d2 = FilteredItems(d, some_test)
于 2012-02-17T14:13:15.623 に答える
2

セマンティクスを明確にするために、次のようなことを考えています:?

class FilteredDictView:
    def __init__(self, base_dict, test):
        self._base_dict = base_dict
        self._test = test
    def __getitem__(self, key):
        value = self._base_dict[key] # might throw KeyError
        if not self._test(key,value):
            throw KeyError(key)
        return value
    # ... implement remaining dict-like-methods ...

もしそうなら、私はそのようなサードパーティのクラスを知りません。残りのメソッドの実装をもう少し簡単にしたい場合は、「UserDict」を基本クラスとして使用することを検討してください。これは基本的には dict の単なるラッパーです (「UserDict.data」属性は、ラップされた dict を格納するために使用されます)。 .

于 2012-02-17T14:15:29.427 に答える