Multi-dimensional Array Implementation in Python 3.2 besides with the coincidence of C#






3.88/5 (7 votes)
A multi dimensional array class with the advance of negative indexes. Used like a[-2, -5, 3] with any dimensions.
Download multiray.py.zip for Python 3.x[^]
Download multiray.cs.zip (updated 05.08.2011)[^]
Introduction
You can easily make use of Multiray
class for issues regarding multidimensional arrays. Now you can download C# version
of multiray completely with the same structure as python version.
Using the Code
The usage is simple:- Initialize
Multiray
object with predefined dimensions:
Python
a = Multiray(2, 5, 20, 6);
C#
using multiray; MultiRay a = new MultiRay(2, 5, 20, 6);
- Assign your data values to multi-index specified cells:
Python
#a[1, 4, 21, 1] will assert an overflow. a[1, 2, 18, 5] = "Any Object";
C#
//a[1, 4, 21, 1] will raise an exception. a[1, 2, 18, 5] = "Any Object";
- Looping is somewhat like jagged arrays. Use
GetLength(d)
for any dimension with index d.
Python
for i in range(a.GetLength(0)): for j in range(a.GetLength(1)): for k in range(a.GetLength(2)): for l in range(a.GetLength(3)): #do anything you want with #a[i, j, k, l]; print("a[{1:3}]={0}".format(a[i, j, k, l], a.Position));
C#
for (int i = 0; i < a.GetLength(0); i++) for (int j = 0; j < a.GetLength(1); j++) for (int k = 0; k < a.GetLength(2); k++) for (int l = 0; l < a.GetLength(3); l++) { a[i, j, k, l] = "Hello World"; Console.WriteLine("a[{0},{1},{2},{3}] = {4}" , i, j, k, l, a[i, j, k, l]); }
_EvaluateIndex
gets real index of given indexes-tuple with this principle:
- if a is a (I x J x K) three dimensional array; let a[i][j][k] nth item in a array. In
Multiray
implementation, n is evaluated by_EvaluateIndex
() method call. - for D = 3, n is thus:
n = i*J*K + j*K + k;
n = i*J*K*T + j*K*T + k*K + t;
_EvaluateIndex
definitely do this:Python
def _EvaluateIndex(self, keys, k): dLen = len(self.Dimensions); #attention! #check recursive deadline: if k == dLen: return keys[-1]; t = 1; #accumulator #multiply t with the given dimensions k to dLen for i in range(k, dLen): t *= self.Dimensions[i] t *= keys[k - 1]; return t + self._EvaluateIndex(keys, k=k+1);C#
private int _EvaluateIndex(int[] keyTuple, int k) { int dLen = this.Dimensions.Length; if (k == dLen) return keyTuple[keyTuple.Length - 1]; int t = 1; for (int i = k; i < dLen; i++) { t *= this.Dimensions[i]; } t *= keyTuple[k - 1]; return t + this._EvaluateIndex(keyTuple, k + 1); }
How is it possible using Multiray object with an indexer?
- Solution is implementing
__getitem__
and__setitem__
:
Python
def __getitem__(self, keyTuple): keys = self._CheckKeys(keyTuple); self.Position = self._EvaluateIndex(keys, k=1); return self._Arr2D[self.Position];
self._CheckKeys
makes checks and conversion of minus indexes(a[2,3,-2]); thenself.Position
is evaluated and is given as index to theself._Arr2D
array.
Python
def __setitem__(self, keyTuple, item): keys = self._CheckKeys(keyTuple); self.Position = self._EvaluateIndex(keys, k=1); self._Arr2D[self.Position] = item
C#
public object this[params int[] keyTuple] { get { int[] keys = this._CheckKeys(keyTuple); this.Position = this._EvaluateIndex(keys, 1); return this._Arr2D[this.Position]; } set { int[] keys = this._CheckKeys(keyTuple); this.Position = this._EvaluateIndex(keys, 1); this._Arr2D[this.Position] = value; } }
- Again
self._CheckKeys()
makes checks and manipulations:
Python
def _CheckKeys(self, keyTuple): assert(len(keyTuple) == len(self.Dimensions)); keyList = list(keyTuple); limit = len(keyList); for i in range(limit): assert(keyList[i] < self.Dimensions[i] \ and keyList[i] >= -self.Dimensions[i]); #for minus indexes: #like a[1,-2] if keyList[i] < 0: keyList[i] += self.Dimensions[i]; return keyList;
C#
private int[] _CheckKeys(int[] keyTuple) { Debug.Assert(keyTuple.Length == this.Dimensions.Length); int limit = keyTuple.Length; int[] keyList = new int[limit]; for (int i = 0; i < limit; i++) { Debug.Assert(keyList[i] < this.Dimensions[i] && keyList[i] >= -this.Dimensions[i]); keyList[i] = keyTuple[i]; //for negative indexes //like a[1,-2] if (keyList[i] < 0) keyList[i] += this.Dimensions[i]; } return keyList; }
Last word
- I found out that "," delimeted indexes are passed in tuples. So when I use a[1,2,3] __getitem__ takes (1,2,3) tuple.
- So positional arguments not needed for now.
Points of Interest
I suffered from invalid mathematical evaluations. By the help of induction, I could eventually implement the right way of function.
History
The previous version lacked c sharp in advance.