문제

나는 큰 매트릭스 (250x250x30 = 1,875,000 셀)로 작업하고 있으며,이 매트릭스에서 각 셀에 대해 임의의 수의 플래그를 설정하는 방법을 원합니다.

내 원래 계획은 250x250x30 목록 배열이며 각 요소는 다음과 같습니다. ["FLAG1","FLAG8","FLAG12"]. 그런 다음 대신 정수 저장으로 변경했습니다. [1,8,12]. 이 정수는 Getter/Setter 기능에 의해 원래 플래그 문자열에 내부적으로 매핑됩니다. 이것은 포인트 당 8 개의 플래그가있는 250MB 만 사용하므로 메모리 측면에서는 괜찮습니다.

내 질문은 : 이런 종류의 데이터를 구성하는 또 다른 명백한 방법을 놓치고 있습니까?

귀하의 제안에 감사드립니다. 나는 몇 가지 제안을 하나의 제안으로 굴려 갔다. 슬프게도 나는 하나의 대답 만 골라 내고 다른 사람들을 향상시켜야한다.

편집 : 여기에 초기 코드 (3D Numpy 배열의 기본 요소로 세트를 사용)는 많은 메모리를 사용했습니다. 이 새 버전은 채워질 때 약 500MB를 사용합니다 randint(0,2**1000).

import numpy

FLAG1=2**0
FLAG2=2**1
FLAG3=2**2
FLAG4=2**3

(x,y,z) = (250,250,30)

array = numpy.zeros((x,y,z), dtype=object)


def setFlag(location,flag):
    array[location] |= flag
def unsetFlag(location,flag):
    array[location] &= ~flag
도움이 되었습니까?

해결책

나는 일반적으로 a Numpy 배열 (아마도 256 개 이상의 별개의 값이 필요할 수 있기 때문에 각각 짧은 INT, 2 바이트) - 2 백만 셀의 경우 4MB 미만이 소요됩니다.

어떤 이유로 든 Numpy 의존성을 감당할 수 없다면 (예 : Numpy를 지원하지 않는 App Engine의 경우) 표준 라이브러리를 사용할 것입니다. 정렬 모듈-1 차원 배열 만 지원하지만 큰 균질 한 배열의 경우 공간 효율적으로 공간 효율적이며, 언급 한 getter/setter 루틴은 자연스럽게 자연스럽게 인덱스 인 싱글 튜플을 완벽하게 "선형화"할 수 있습니다. 정수 색인 1-D 배열로 인덱스.

일반적으로 균질하고 밀집된 벡터 또는 숫자의 매트릭스가있을 때마다 Numpy (또는 배열)를 고려하십시오. Python 내장 목록은이 사용 사례에서 공간을 많이 낭비합니다 (사용하지 않고 일반성이없고 일반성 때문에 사용하지 않고 일반성이 있습니다. 여기에 필요하지 않습니다!-), 메모리 절약은 간접적으로 시간 절약 (더 나은 캐싱, 더 적은 수준의 간접 등)을 번역합니다.

다른 팁

모든 단일 셀에 깃발이 있으면 솔루션이 정상입니다. 그러나 셀의 작은 하위 섹션만이 실제로 원하는 깃발을 갖는 희소 데이터 세트로 작업하는 경우 사전입니다. 키는 셀의 위치에 대한 튜플이고 값은 솔루션에서와 같은 플래그 목록입니다.

allFlags = {(1,1,1):[1,2,3], (250,250,30):[4,5,6]}

여기에는 1,1,1 셀에 플래그 1,2, 3이 있고 셀 250,250,30에는 깃발이 4,5, 6에 있습니다.

편집- 고정 키 튜플, 감사합니다 Andre 및 Dictionary Syntax.

두 가지 값의 다른 힘을 가진 일부 상수를 다음과 같이 정의 할 수 있습니다.

FLAG1 = 0x01
FLAG8 = 0x02
FLAG12 = 0x04
...

부울 논리와 함께 사용하여 플래그를 하나의 정수에만 저장합니다.

flags = FLAG1 | FLAG8

플래그가 활성화되어 있는지 확인하려면 & 운영자:

flag1_enabled = flags & FLAG1

플래그가 활성화되면이 표현식은 0이 아닌 값을 반환하며, 이는 부울 작업에서 True로 평가됩니다. 플래그가 비활성화되면 표현식이 0이되며 부울 연산에서 거짓으로 평가됩니다.

플라이급 패턴을 사용하여 셀 특성을 공유하는 것을 고려하십시오.

http://en.wikipedia.org/wiki/flyweight_pattern

비츠 세트 고정 크기 정수 (int type) 만 사용하여 한 번에 많은 플래그를 저장할 수 있기 때문에 원하는 것입니다.

Robbie의 제안을 한 걸음 더 한 걸음 더 나아가 ...

flags = set()
x, y, flag = 34, 201, 3
flags.add((x, y, flag)) # set flag 3 at position (34, 201)
if (3, 2, 1) in flags: # check if flag 1 is at position (3, 2)
    # do something
else:
    # do something else

도우미 클래스를 만들 수도 있습니다.

class Flags(object):
    def __init__(self):
        self.data = set()
    def add(self, x, y, flag):
        self.data.add((x, y, flag))
    def remove(self, x, y, flag):
        self.data.remove((x, y, flag))
    def contains(self, x, y, flag):
        return (x, y, flag) in self.data

Python의 특별한 방법과 같은 특별한 방법을 구현할 수도 있습니다 __contains__ 작업하기가 더 쉬워집니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top