2013-03-10 58 views
0

我需要建立一個數據結構,像這樣的:python - 哪個數據結構用作一個數組的字典?

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

事情是我建立它在「香豔」的方式,在每一次得到一個更多的項目放在一個隨機k代表一個隨機密鑰,即我需要隨機訪問,我需要內部字典是可變的。

所以我的問題分爲兩個:

  1. 推薦的類型外字典。

  2. 內部字典的推薦類型。

對我來說,「最佳」解決方案將是一個可變的namedtuples數組,只有這個不存在。

我可以使用namedtuples列表,然後用新數據重新創建每個列表,但這聽起來超級浪費,列表不是隨機訪問高效的,而是所有重寫的相同數據。

有沒有我不知道的一些神奇的新結構?

編輯:使用的 例如:

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:

事實證明,列表實際上做support random access

+0

我不知道這是可能的,如果我理解正確的問題。像dict這樣的可變對象不能是字典鍵。 – millimoose 2013-03-10 13:29:25

+0

無論如何,目前還不清楚你想要完成什麼。你能舉一個例子說明這個數據結構是如何「折衷地」構建的?即給定單個更新之前和之後的狀態? – millimoose 2013-03-10 13:30:44

+0

我不知道我明白..我在哪裏建議,字典將作爲密鑰? – phistakis 2013-03-10 13:31:46

回答

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 
+0

或'__slots__ = ['field {}'。format(i + 1)for i in xrange(3)]'(當字段更多時很有用) – nneonneo 2013-03-10 13:37:12

+0

@nneonneo:我應該用'foo','bar'然後用'baz'作爲字段名稱;他們是說明性的。 – 2013-03-10 13:38:32

+0

這正是我所需要的,謝謝! – phistakis 2013-03-10 13:49:27

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, ...] 
0

鑑於你r示例:

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 
相關問題