Click here to Skip to main content
11,437,319 members (62,320 online)
Click here to Skip to main content

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

, 8 Mar 2012 GPL3
Rate this:
Please Sign up or sign in to vote.
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:
  1. Initialize Multiray object with predefined dimensions:
    Python
    a = Multiray(2, 5, 20, 6);
    
    C#
    using multiray;
    MultiRay a = new MultiRay(2, 5, 20, 6);
    
  2. 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";
    
  3. 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;
  • for D = 4(I x J x K x T :: i, j, k, t) n is thus:
    • n = i*J*K*T + j*K*T + k*K + t;
  • We multiply the first key with J, K and T; second key with K and T; third with T and fourth with 1
  • So we need to multiply first index with keys[1]*keys[2]*keys[3] second key with keys[2]*keys[3] and so on...
  • _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]); then self.Position is evaluated and is given as index to the self._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.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

lampiclobe
Software Developer
Turkey Turkey
I am a software developer emphasizing algorithm side of development.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 8 Mar 2012
Article Copyright 2012 by lampiclobe
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid