HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Add two 4-D arrays in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
twoarrayspythonadd

Problem

I have two arrays, each with shape (1, 51, 150, 207)

I need to add them such that:

newarray[0][0][0][0] = array1[0][0][0][0] + array2[0][0][0][0]
newarray[0][0][0][1] = array1[0][0][0][1] + array2[0][0][0][1]


for every element in the array.

Currently I'm creating a new array using nested while loops but this approach is extremely time consuming. Can anyone offer a better solution?

H = 0
NS = 0
EW = 0
height = []
while H < 51:
    northsouth = []
    while NS < 150:
        eastwest = []
        while EW < 207:
            eastwest.append(PH[0][H][NS][EW] + PHB[0][H][NS][EW])
            EW += 1
            print eastwest
        northsouth.append(eastwest)
        NS += 1
        print northsouth
    height.append(northsouth)
    H =+ 1

Solution

Firstly, code that looks like:

foo = 0
while foo < bar:
    ...  # foo doesn't change here
    foo += 1


is a bad sign. In Python, this can immediately be simplified, using range, to:

for foo in range(bar):
    ...


Secondly, hard-coding the shape of your "arrays" everywhere (having the literals 51, 150 and 207 in the code itself), referred to as "magic numbers", is poor practice in every programming language. These are the lengths of each sub-list, so should be calculated as needed using len(...). This makes the code more flexible; it can now be easily applied to add arrays of other sizes. it's also slightly awkward to hard-code the depth of the addition (i.e. that it only handles four-dimensional arrays).

Thirdly, however, code like:

for index in range(len(sequence)):
    element = sequence[index]
    ...


is generally better replaced with:

for element in sequence:
    ...


where you need the index too, you can use enumerate, and where you need to iterate over multiple iterables you can use zip; Python has lots of handy functions for dealing with iterables (see also itertools).

Fourthly, when you have a loop appending to a list, it's usually more efficient to replace it with a "list comprehension". For example:

foo = []
for bar in baz:
    foo.append(bar)


can be replaced by:

foo = [bar for bar in baz]


Finally, however, this is totally trivial if you switch to numpy, which is extremely helpful for manipulating arrays:

>>> import numpy as np
>>> arr1 = np.random.randint(1, 10, (1, 51, 150, 207))
>>> arr2 = np.random.randint(1, 10, (1, 51, 150, 207))
>>> arr1 + arr2  # wasn't that easy!
array([[[[11, 13, 14, ...,  9, 14,  8],
         [15,  4, 10, ..., 14, 10, 16],
         [11, 11,  9, ...,  4,  9,  9],
         ..., 
         [17, 10, 14, ..., 10, 12, 12],
         [12, 11, 14, ...,  7,  8,  8],
         [ 9, 11,  6, ...,  3, 11,  8]],

        [[10, 15, 16, ..., 11, 16, 10],
         [17, 17,  8, ...,  8,  7,  8],
         [11,  7,  2, ..., 16, 11,  5],
         ..., 
         [15, 10, 16, ..., 16, 13,  9],
         [15,  8,  7, ..., 13,  5,  6],
         [ 4,  5, 10, ...,  7, 10, 10]],

        [[11, 10,  4, ..., 10,  7, 11],
         [12,  3, 14, ..., 11, 12, 12],
         [ 6, 11, 16, ..., 14,  9, 12],
         ..., 
         [18, 10, 11, ..., 13, 14,  9],
         [11, 11, 10, ...,  9, 13, 12],
         [10, 10, 10, ..., 12, 14,  8]],

        ..., 
        [[16, 11, 12, ..., 13, 13,  9],
         [ 7, 15, 10, ...,  9, 11,  5],
         [ 5, 11, 14, ..., 14,  4, 11],
         ..., 
         [15, 13,  6, ..., 17,  6, 10],
         [ 9, 12,  7, ...,  7, 17, 11],
         [12,  9, 10, ...,  4,  9,  5]],

        [[15, 12, 10, ...,  5, 12, 15],
         [17, 14, 15, ..., 13, 11,  8],
         [13, 10, 10, ...,  8,  4,  8],
         ..., 
         [12,  9, 10, ...,  9,  7, 12],
         [13, 12, 17, ...,  7, 13, 10],
         [13,  6,  8, ..., 15, 13,  7]],

        [[ 9,  8,  8, ...,  6, 10,  2],
         [ 9, 15, 14, ..., 14,  4,  5],
         [ 3, 12, 12, ...,  5, 10, 14],
         ..., 
         [ 6, 11, 15, ..., 11,  4, 15],
         [ 4, 12, 14, ..., 12, 11,  9],
         [10,  3,  5, ...,  5,  7, 10]]]])

Code Snippets

foo = 0
while foo < bar:
    ...  # foo doesn't change here
    foo += 1
for foo in range(bar):
    ...
for index in range(len(sequence)):
    element = sequence[index]
    ...
for element in sequence:
    ...
foo = []
for bar in baz:
    foo.append(bar)

Context

StackExchange Code Review Q#94702, answer score: 9

Revisions (0)

No revisions yet.