2013-03-10 1 views
0

나는 이와 같은 데이터 구조를 구축 할 필요가 : 것은 나는 모든 시간이에 대한 임의의 K에 넣어 한 번 더 아이템을 얻을에 "취사"방법에 짓고 있어요된다python - 어떤 데이터 구조가 dicts의 배열로 사용할 수 있습니까?

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

무작위 키, 즉 랜덤 액세스가 필요합니다. 그리고 내부 다이어그램을 변경할 수 있어야합니다.

그래서 제 질문은 두 가지로 구분됩니다

  1. 외부 DICT에 권장되는 유형입니다.

  2. 내부 dict의 권장 유형입니다.

나를위한 "최상의"해결책은 변경 가능한 명명 된 튜플의 배열 일 것이고, 이것은 단지 존재하지 않습니다.

명명 된 튜플 목록을 사용한 다음 새 데이터로 각 테이블을 다시 만들 수는 있지만 목록에 무작위 액세스가 효율적이지 않고 동일한 데이터의 모든 다시 쓰기가 필요하지 않습니다.

내가 알고 있지 못하는 새로운 마법의 구조가 있습니까?

편집 : 사용의 예 :

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 :

그것의 양을 제한하는 __slots__를 사용하여 목록을 실제로 support random access

+0

는 내가 제대로 질문을 이해한다면이 가능 모르겠어요. 'dict'와 같은 변경 가능한 객체는 사전 키가 될 수 없습니다. – millimoose

+0

어쨌든, 당신이 성취하고자하는 것은 분명하지 않습니다. 이 데이터 구조가 "절충 적"으로 구축되는 방법에 대한 예를 보여줄 수 있습니까? 나는. 주어진 단일 업데이트에 대한 이전 및 이후 상태? – millimoose

+0

내가 이해할 수 있을지 모르겠다. 어디에서 dicts가 키로서 기능 할 것이라고 제안 했는가? – phistakis

답변

6

당신은 사용자 정의 클래스를 만들 수 DO 밝혀 아마도 사용 된 메모리 :

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' 

당신은 슬롯 의미있는 이름을주고, 내가 예에서 사용 된 것보다 당신의 클래스에 대한 더 나은 이름을 선택 바랍니다.

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

또는 xrange (3)에서 i에 대해 (__slots__ = [ 'field {}') format (더 많은 필드가있을 때 유용) – nneonneo

+0

@nneonneo :'foo','bar' 그 다음 필드 이름에'baz'; 그들은 설명의 대상이었다. –

+0

그게 바로 내가 필요한 것입니다, 감사합니다! – phistakis

2

defaultdict 바로 여기 느낀다 :

는 고정 된 크기 목록을 원하는 경우, defaultdict이있다
from collections import defaultdict 

d = defaultdict(lambda: defaultdict(int)) 

d[3][4] = 10 

:-)

namedtuple() 패턴을 확장하려면, 여기에 일반 공장 기능입니다 너는 :

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

d[3][4] = 10 
# d[3] is now [None, None, None, None, 10, None, None, ...] 
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 
관련 문제