简体   繁体   中英

Python - Multi-Dimensional Arrays

Python does not provide built-in support for multi-dimensional arrays. I need to develop an 11-dimensional array and a set of functions to operate on it (mostly linear algebra, vector arithmetics). However, no external library import is allowed . I have a code in C and trying to port it to Python:

typedef vec3_t float[3];
vec3_t Array[dim0][dim1][dim2][dim3][dim4][dim5][dim6][dim7][dim8][dim9][dim10];
Array[0][0][0][0][0][0][0][0][0][0][1] = {1.0, 0.0, 0.0};

How can it be implemented in Python effectively (with good readability )?

PS: For Python 2.5 version at most.

With so many dimensions, and no library imports allowed, I'd go (as the basic choice) for a dictionary indexed by tuples. This way, you get very nice syntax for simple indexing:

Array = dict()
Array[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] = [1.0, 0.0, 0.0]

You'll probably want to wrap it in a class to add functionality beyond simple indexing, but, not knowing what it is that you want beyond that (initialization/defaults? slicing? iteration? etc, etc...), it's just too hard to guess. If you can specify precisely all that you want to do with that "multi-dimensional array", it shouldn't be hard to show you the code that best provides it!

I've written a Matrix class here:

Multidimensional array in Python

It can be used like this:

m = Matrix(4,5,2,6)
m[2,3,1,3] = 'x'
m[2,3,1,3] // -> 'x'

Another possibility would be to create a 1-dimensional array and then read/write it using functions that take 11 index arguments. You multiply out the indices (based on the max for each dimension) to calculate a position in the array. The get/set functions themselves won't be all that pretty (with 11 indices) but once you have them written, getting and setting array indices will look almost as clean as it does in C. I'm not sure how performance would compare to that of nested lists but my guess is that it would be favorable.

The basic concept can be shown with 2 dimensions:

def readArray2(arr,i1,i2,dim2):
    index = i1 * dim2 + i2
    return arr[index]

It gets more complicated with more dimensions, though:

def readArray3(arr,i1,i2,i3,dim2,dim3):
    index = i1 * dim2 * dim3 + i2 * dim3 + i3
    return arr[index]

And so on for larger arrays. You could generalize this to a variable number of dimensions. I'd probably put the indices and dimensions into lists and then iterate over them.

A potentially very legible solution, though probably performance-poor, would use a dict with eleven-element tuples as keys:

>>> d[0,1,2,3,4,5,6,7,8,9,0] = [1.0, 0.0, 0.0]

This also allows you to store the coordinate vectors and pass them around as single objects:

>>> coord = (0,1,2,3,4,5,6,7,8,9,0)
>>> d[coord]
[1.0, 0.0, 0.0]

You could enforce key integrity by either using your own class or a subclass of dict:

>>> class Space(dict):
>>>     def __setitem__(self, key, value):
>>>         if len(key) == 11:
>>>             dict.__setitem__(self, key, value)
>>>         else:
>>>             raise IndexError("Keys must be eleven-dimensional vectors.")

You could improve performance by using your own class with the same __getitem__ / __setitem__ interface, but that need not even be done at first.

"""
Create multi-dimensional array for given dimensions - (x1, x2, x3, ..., xn)

@author: Naimish Agarwal
"""


def multi_dimensional_array(value, *dim):
    """
    Create multi-dimensional array
    :param dim: a tuple of dimensions - (x1, x2, x3, ..., xn)
    :param value: value with which multi-dimensional array is to be filled
    :return: multi-dimensional array
    """

    if len(dim) > 1:
        return [multi_dimensional_array(value, *dim[1:]) for _ in xrange(dim[0])]
    else:
        return [value for _ in xrange(dim[0])]


if __name__ == "__main__":
    multi_array = multi_dimensional_array(False, *(2, 3, 1))
    print multi_array

Prefer numpy.ndarray for multi-dimensional arrays.

"Multi-dimension" is just a fancy term to mean "many memory locations". If you look at it in a broader sense, they are just really "1 dimensional". Anyway, to suggest an alternative, you can use dictionaries.

>>> d={}
>>> d[0]={}
>>> d[0][0]="1"
>>> d[0]
{0: '1'}

Create your dicts this way to your "11"th dimension.

You could use lists:

list = [ [ [ '' for i in range(dim0) ] for j in range(dim1) ] for k in range(dim2) ]

and so on after that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM