0

次のようなデータ構造を構築する必要があります。

{
    key: {k: v for k in range(fixed_small_number)}
    for key in range(fixed_large_number)
}

重要なのは、「折衷的な」方法で構築していることです。ランダムキーのランダムkに入れるアイテムをもう1つ取得するたびに、つまり、ランダムアクセスが必要であり、内部dictを変更可能にする必要があります。

だから私の質問は2つに分かれています:

  1. 外側の口述に推奨されるタイプ。

  2. 内側の口述に推奨されるタイプ。

私にとっての「最良の」解決策は、可変の名前付きタプルの配列ですが、これだけは存在しません。

名前付きタプルのリストを使用して、新しいデータでそれぞれを再作成することもできますが、リストがランダムアクセス効率でなく、同じデータがすべて書き換えられるため、非常に無駄に聞こえます。

私が知らない魔法の新しい構造はありますか?

編集:使用例:

for key, k, v in [('a', 1, 2), ('b', 1, 3), ('a', 2, 1), ('a', 3, 1), ('b', 3, 1) ...]:
    my_structre[key][k] = v

EDIT2:

リストは実際にはランダムアクセスをサポートしていることがわかりました

4

3 に答える 3

6

__slots__おそらく使用されるメモリの量を制限するために使用して、カスタム クラスを構築できます。

class MutableEfficientNamedList(object):
    __slots__ = ('field1', 'field2', 'field3')

    def __init__(self, *values):
        for k, v in zip(self.__slots__, values):
            setattr(self, k, v)

    def __getitem__(self, i):
        return getattr(self, self.__slots__[i])

    def __setitem__(self, i, v):
        return setattr(self, self.__slots__[i], v)

    def __repr__(self):
        return '{}({})'.format(type(self).__name__, 
            ', '.join(repr(getattr(self, s)) for s in self.__slots__))

次に、それらを構造で使用します。名前付きタプルと同じように使用できますが (インデックス名前によるアクセスが許可されます)、変更が可能です。__slots__各インスタンスのメモリ フットプリントを使用することにより、低いままです。

>>> menl = MutableEfficientNamedList('foo', 'bar', 'baz')
>>> menl
MutableEfficientNamedList('foo', 'bar', 'baz')
>>> menl.field1
'foo'
>>> menl[0]
'foo'
>>> menl[1]
'bar'
>>> menl[1] = 'spam'
>>> menl.field2
'spam'

もちろん、スロットには意味のある名前を付けてください。私の例で使用した名前よりも適切な名前をクラスに付けてください。:-)

パターンを拡張するためにnamedtuple()、一般的なファクトリ関数を次に示します。

def namedlist(name, *attrs):
    """Create a named list class named `name` with attributes `attrs`.
       `attrs` must be strings representing valid Python identifiers.
    """
    class MutableEfficientNamedList(object):
        __slots__ = attrs

        def __init__(self, *values):
            for k, v in zip(self.__slots__, values):
                setattr(self, k, v)

        def __getitem__(self, i):
            return getattr(self, self.__slots__[i])

        def __setitem__(self, i, v):
            return setattr(self, self.__slots__[i], v)

        def __repr__(self):
            return '{}({})'.format(type(self).__name__, 
                ', '.join(repr(getattr(self, s)) for s in self.__slots__))

    MutableEfficientNamedList.__name__ = name
    return MutableEfficientNamedList

MyList = namedlist('MyList', 'foo', 'bar', 'baz')
nl = MyList(1, 2, 3)
print nl  # MyList(1, 2, 3)
print nl.bar  # 2
print nl[1]  # 2
于 2013-03-10T13:32:02.550 に答える
2

defaultdictここに感じます:

from collections import defaultdict

d = defaultdict(lambda: defaultdict(int))

d[3][4] = 10

固定サイズのリストdefaultdictが必要な場合は、以下をカバーしましたか?

d = defaultdict(lambda: [None]*fixed_small_number)

d[3][4] = 10
# d[3] is now [None, None, None, None, 10, None, None, ...]
于 2013-03-10T13:32:29.450 に答える
0

あなたの例を考えると:

for key, k, v in [('a', 1, 2), ('b', 1, 3), ('a', 2, 1), ('a', 3, 1), ('b', 3, 1) ...]:
    my_structre[key][k] = v

解決策は確かにを使用することdefaultdictです。

from collections import defaultdict

d = defaultdict(dict)
for key, k, v in [('a', 1, 2), ('b', 1, 3), ('a', 2, 1), ('a', 3, 1), ('b', 3, 1)]:
    d[key][k] = v

答え:

{'a': {1: 2, 2: 1, 3: 1}, 'b': {1: 3, 3: 1}}

関数として:

def method(iter_of_3_item_iters):
    d = defaultdict(dict)
    for (a, b, c) in iter_of_3_item_iters:
        d[a][b] = c
    return d
于 2013-03-10T13:39:03.387 に答える