Skip to content
Advertisement

Python – Reverse every other slice of an array

I wrote some code to reverse every other slice of rows.

import numpy as np
test_arr = np.arange(120).reshape(12,10)
test_arr = test_arr.tolist()
def rev_rows(matrix):
    for I in range(len(matrix)): #did this to get the index of each row
        if((int(I / 4) % 2) == True): #selct rows whose index divided by 4 truncate to an odd number
            print("flip")
            matrix[I].reverse() #flip said row
        print(matrix[I])

rev_rows(test_arr)

There has to by an easier and more efficient way of doing this. I was thinking another way would be to use list operators like slices, but I can’t think of one which is faster than this. Is there an easier way with numpy?

Note: the length of the matrix would be divisible by 4. i.e. (4×10), (8×10), …

EDIT:

Sorry about the ambiguous usage of slice. What I meant by a slice is a set of rows (like test_arr[3] -> test_arr[7]). So, reversing every other slice would be reversing every row between indexes 3 and 7. I was in my little blurb about the slicing operator I was talking about this operator -> [3:7]. I don’t have experience with them, and I read somewhere that they are called slicing, my bad.

Advertisement

Answer

Update

The question wasn’t very clear, so my original answer didn’t solve it. Here is a working example.

With a loop

The loop version’s performance is more predictable, because it’s not always clear when a reshape will trigger a copy.

>>> test_arr = np.arange(120).reshape(12, 10)
>>> for i in range(4, 8):
...     test_arr[i::8] = test_arr[i::8,::-1]
>>> test_arr
array([[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19],
       [ 20,  21,  22,  23,  24,  25,  26,  27,  28,  29],
       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],
       [ 49,  48,  47,  46,  45,  44,  43,  42,  41,  40],
       [ 59,  58,  57,  56,  55,  54,  53,  52,  51,  50],
       [ 69,  68,  67,  66,  65,  64,  63,  62,  61,  60],
       [ 79,  78,  77,  76,  75,  74,  73,  72,  71,  70],
       [ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89],
       [ 90,  91,  92,  93,  94,  95,  96,  97,  98,  99],
       [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
       [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]])
>>> 

Without a loop

A loopless version, as asked by @KellyBundy.

>>> test_arr = np.arange(120).reshape(12, 10)
>>> temp_arr = test_arr.reshape(test_arr.shape[0]//4, 4, test_arr.shape[1])
>>> temp_arr[1::2] = temp_arr[1::2,:,::-1]
>>> test_arr = temp_arr.reshape(*test_arr.shape)
>>> test_arr
array([[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19],
       [ 20,  21,  22,  23,  24,  25,  26,  27,  28,  29],
       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],
       [ 49,  48,  47,  46,  45,  44,  43,  42,  41,  40],
       [ 59,  58,  57,  56,  55,  54,  53,  52,  51,  50],
       [ 69,  68,  67,  66,  65,  64,  63,  62,  61,  60],
       [ 79,  78,  77,  76,  75,  74,  73,  72,  71,  70],
       [ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89],
       [ 90,  91,  92,  93,  94,  95,  96,  97,  98,  99],
       [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
       [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]])
>>>

Original answer

You can do this with slicing: test_arr[::2] = test_arr[::2,::-1] or test_arr[1::2] = test_arr[1::2,::-1].

See the examples:

>>> import numpy as np
>>> test_arr = np.arange(120).reshape(12, 10)
>>> test_arr
array([[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19],
       [ 20,  21,  22,  23,  24,  25,  26,  27,  28,  29],
       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],
       [ 40,  41,  42,  43,  44,  45,  46,  47,  48,  49],
       [ 50,  51,  52,  53,  54,  55,  56,  57,  58,  59],
       [ 60,  61,  62,  63,  64,  65,  66,  67,  68,  69],
       [ 70,  71,  72,  73,  74,  75,  76,  77,  78,  79],
       [ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89],
       [ 90,  91,  92,  93,  94,  95,  96,  97,  98,  99],
       [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
       [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]])
>>> test_arr[::2] = test_arr[::2,::-1]
>>> test_arr
array([[  9,   8,   7,   6,   5,   4,   3,   2,   1,   0],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19],
       [ 29,  28,  27,  26,  25,  24,  23,  22,  21,  20],
       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],
       [ 49,  48,  47,  46,  45,  44,  43,  42,  41,  40],
       [ 50,  51,  52,  53,  54,  55,  56,  57,  58,  59],
       [ 69,  68,  67,  66,  65,  64,  63,  62,  61,  60],
       [ 70,  71,  72,  73,  74,  75,  76,  77,  78,  79],
       [ 89,  88,  87,  86,  85,  84,  83,  82,  81,  80],
       [ 90,  91,  92,  93,  94,  95,  96,  97,  98,  99],
       [109, 108, 107, 106, 105, 104, 103, 102, 101, 100],
       [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]])
>>> 

If, instead, you wanted to reverse rows with odd indices, you’d do

>>> test_arr = np.arange(120).reshape(12, 10)
>>> test_arr[1::2] = test_arr[1::2,::-1]
>>> test_arr
array([[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 19,  18,  17,  16,  15,  14,  13,  12,  11,  10],
       [ 20,  21,  22,  23,  24,  25,  26,  27,  28,  29],
       [ 39,  38,  37,  36,  35,  34,  33,  32,  31,  30],
       [ 40,  41,  42,  43,  44,  45,  46,  47,  48,  49],
       [ 59,  58,  57,  56,  55,  54,  53,  52,  51,  50],
       [ 60,  61,  62,  63,  64,  65,  66,  67,  68,  69],
       [ 79,  78,  77,  76,  75,  74,  73,  72,  71,  70],
       [ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89],
       [ 99,  98,  97,  96,  95,  94,  93,  92,  91,  90],
       [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
       [119, 118, 117, 116, 115, 114, 113, 112, 111, 110]])
>>> 
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement