2011-01-20 13 views
0

私はテーブルを作成するために次のクラスを使用していますが、より高速にするだけでなく、それとのやりとりを高速化する方法を見つける必要があります:Pythonリスト操作の高速化とカスタムテーブルクラスの比較

class Table(object): 
    """a three dimensional table object""" 
    def __init__(self, xsize=1, ysize=1, zsize=1): 
     self.xsize = xsize 
     self.ysize = ysize 
     self.zsize = zsize 
     self.data = [0] * (xsize * ysize * zsize) 

    def __getitem__(self, key): 
     x, y, z = self.__extractIndices(key) 
     return self.data[x + self.xsize * (y + self.ysize * z)] 

    def __setitem__(self, key, value): 
     x, y, z = self.__extractIndices(key) 
     self.data[x + self.xsize * (y + self.ysize * z)] = value 

    def __extractIndices(self, key): 
     x = y = z = 0 
     if (self.ysize > 1): 
      if (self.zsize > 1): 
       if len(key) != 3: 
        raise IndexError 
       else: 
        x, y, z = key 
      elif len(key) != 2: 
       raise IndexError 
      else: 
       x, y = key 
     elif not isinstance(key, int): 
      raise IndexError 
     else: 
      x = key 
     return (x, y, z) 

    def resize(self, xsize=1, ysize=1, zsize=1): 
     """resize the table preserving data""" 
     oldlist = list(self.data) 
     self.data = [0] * (xsize * ysize * zsize) 
     self.xsize = xsize 
     self.ysize = ysize 
     self.zsize = zsize 
     for i in range(0, oldlist): 
      self.data[1] = oldlist[i] 

オンポイント2つのリストのデータがそれぞれzの と同等であるかどうかを調べる必要があります。

for x in range(self.map.width - 1): 
     for y in range(self.map.height - 1): 
      tempflag = False 
      #layer 1 
      if self.data[x, y, 0] != self.map.data[x, y, 0]: 
       tempflag = True 
       layer1flag = True 
      #layer 2 
      if self.data[x, y, 1] != self.map.data[x, y, 1]: 
       tempflag = True 
       layer2flag = True 
      #layer 3 
      if self.data[x, y, 2] != self.map.data[x, y, 2]: 
       tempflag = True 
       layer3flag = True 
      #copy the data if it changed 
      if tempflag: 
       self.data = copy.deepcopy(self.map.data) 
       previewflag = True 

上明確に、これは私が考えられる。このと検討を行うことが最も遅い方法ですからself.dataself.map.dataは、テーブルクラスのインスタンスであること、私は200 * 200 * 3 =12万エントリのサイズを持って比較していますこれらのテーブルの一部。私はできるだけ早くこれが必要です。

私はそう

tempflag = False 
#layer 1 
slicepoint1 = 0 
slicepoint2 = self.data.xsize * self.data.ysize * 1 
data1 = self.data.data[slicepoint1:slicepoint2] 
data2 = self.map.data.data[slicepoint1:slicepoint2] 
if data1 != data2: 
    tempflag = True 
    layer1flag = True 
#layer 2 
slicepoint1 = self.data.xsize * self.data.ysize * 1 
slicepoint2 = self.data.xsize * self.data.ysize * 2 
data1 = self.data.data[slicepoint1:slicepoint2] 
data2 = self.map.data.data[slicepoint1:slicepoint2] 
if data1 != data2: 
    tempflag = True 
    layer2flag = True 
#layer 3 
slicepoint1 = self.data.xsize * self.data.ysize * 2 
slicepoint2 = self.data.xsize * self.data.ysize * 3 
data1 = self.data.data[slicepoint1:slicepoint2] 
data2 = self.map.data.data[slicepoint1:slicepoint2] 
if data1 != data2: 
    tempflag = True 
    layer3flag = True 
#copy the data if it changed 
if tempflag: 
    self.data = copy.deepcopy(self.map.data) 
    previewflag = True 

のような1つのzのためのすべてのエントリをスライスする上記の比較を書き換えると考えられてきた、それはより速く、それが大幅に向上させることができているように、それはまだらしい行くようにこれは思えるながら。例えば、numpyを使用してTableクラスの中にデータリストを構築することはできないでしょうか? numpyのの使用は本当に速いので、私は内のデータを使用することができ、テーブルをループに私を許可するかどう

は、私はそれはおそらく

それもいいだろうことができます限り速く実行するには、このクラスと、このチェックが必要それブリット操作はタイルマップ

を構築するために私はは、テーブルのデータがself.dataに格納されていることをテーブルクラス、特に実際の一般的なインタフェースを維持する必要があるのですか要約速度が缶に

オペラのイオンはnumpyを使って増やすことができますか?もしそうなら、私はどのようにそれを行うことができますか?

+1

これは、3Dデータを格納するのが非常に遅く厄介な方法のようです。 Pythonでネストされたリストを使用したとしても、より早く簡単になる可能性がありますが、おそらくnumpyの配列はもっと良い答えでしょう。 –

答えて

1

これは間違いなくNumPyのアプリケーションです!インデックス作成と比較は既にNumPyで処理されているため、コードをスピードアップするだけでなく、コードを大幅に簡略化します。あなたはNumPyを学ぶためにいくつかのチュートリアルを読む必要があります - この場合、あなたを得るためのほんの少しのヒント。

通常、私は単純にカスタムの配列クラスを定義するためにnumpy.ndarrayから派生するだろうが、あなたは間違いなくnumpy.ndarray.dataと衝突data属性を、必要があると述べました。あなたのクラスは

eq = self.data == self.data.map 
layerflags = eq.reshape(-1, 3).any(axis=0) 
if layerflags.any(): 
    self.data[:] = self.map.data 

class Table(object): 
    def __init__(self, xsize=1, ysize=1, zsize=1): 
     self.data = numpy.zeros((xsize, ysize, zsize)) 

    def __getitem__(self, key): 
     return self.data[key] 

    def __setitem__(self, key, value): 
     self.data[key] = value 

    def resize(self, xsize=1, ysize=1, zsize=1): 
     # This only works for increasing the size of the data, 
     # but is easy do adapt to other cases 
     newdata = numpy.zeros((xsize, ysize, zsize)) 
     shape = self.data.shape 
     newdata[:shape[0], :shape[1], :shape[2]] = self.data 
     self.data = newdata 

あなたの比較コードを簡素化するに簡略化され、それはあまりにも多くの高速になります!

+0

おそらく私は何かが不足しています、その比較はどのように形状が返されるオブジェクトを返しますか?おそらく、この操作を説明する参照資料に私をリンクすることはできますか?それは私があなたがより良い答えを理解するのを助けるでしょう。ありがとう。私は現在Numpyのドキュメントを読んでいますので、あなたが答える前にそれを見つけるでしょう。私がこのコメントを編集します。 – Ryex

+0

@Ryex:NumPyのすべての操作はベクトル化されています。つまり、要素ごとに実行されます。 2つの配列の '=='はboolの配列を返し、2つの配列のどの要素が等しいかを示します。 –

+0

今、それはクールです。簡単な質問として、私のバージョンのテーブルクラスの同じフォーマットのリストをnumpy配列に変換する方法があります。ここで[0,0,0]インデックス操作は同じ値を返しますか?逆も同様です。これらの2つの操作は、インポートとエクスポートの方法で一度実行する必要がありますが、その間に速度は実に必要ではありません。 – Ryex

2

私はそう思います、あなたはおそらく速度の多くを得ることができるnumpyを使用しています。

は、だけでなく、あなたは、スライスを作ることができますが、長方形を作ることができ、そしておそらく立方スライスも、例:

>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]]) 
>>> a[:2,1:] 
array([[2, 3], 
     [5, 6]]) 

は、私はあなたが達成したいのかわからないが、あなたも簡単にnumpyの配列の要素ごとに比較することができます:

>>> numpy.array([1,2,3])==numpy.array([9,2,3]) 
array([False, True, True], dtype=bool) 

ご質問がある場合は、お気軽にコメントしてください。

関連する問題