1

I have two numpy arrays:

Values = numpy.array([5, 6, 7, 8, 1, 2, 3, 14, 15, 16])
Lengths = numpy.array([4, 3, 3])   

What would be an efficient way to in numpy to reverse the order within the sublist to get this?

[8, 7, 6, 5, 3, 2, 1, 16, 15, 14]

I have tried for loop, but I believe there should be a more efficient way to do it using numpy functions.

1
  • For lists and arrays, indexing with ::-1 reverses Commented Aug 18, 2023 at 19:34

5 Answers 5

1

You can do this by splitting the array (using np.split) at the desired indices, given by np.cumsum(Lengths), and then concatenating (using np.concatenate) them after each is reversed.

import numpy as np

Values = np.array([5, 6, 7, 8, 1, 2, 3, 14, 15, 16])
Lengths = np.array([4, 3, 3])

res = np.concatenate([split[::-1] for split in np.split(Values, np.cumsum(Lengths))])
print(res)

Output:

[ 8  7  6  5  3  2  1 16 15 14]
Sign up to request clarification or add additional context in comments.

Comments

1

For a vectorial solution, you can craft a sorter array with np.repeat, then use np.argsort to reorder your array

a = np.repeat(np.arange(len(Lengths)), Lengths)[::-1]
# array([2, 2, 2, 1, 1, 1, 0, 0, 0, 0])

out = Values[len(Values)-1-np.argsort(a)]

Output:

array([ 8,  7,  6,  5,  3,  2,  1, 16, 15, 14])

Intermediate:

len(Values)-1-np.argsort(a)
# array([3, 2, 1, 0, 6, 5, 4, 9, 8, 7])

Comments

0
import numpy as np

Values = np.array([5, 6, 7, 8, 1, 2, 3, 14, 15, 16])
Lengths = np.array([4, 3, 3])

splits = np.split(Values, np.cumsum(Lengths)[:-1]) #splits into 3 parts
reversed_list = [np.flip(split) for split in splits] #flip/reverse all the 3 parts

result = np.concatenate(reversed_list) # join all 3 parts
print(result)

Comments

0

According to this discussion, slicing is the among the fastest techniques, you can use for splitting. The following code uses only slicing and hence doesn't use any additional space or copying.

import numpy
Values = numpy.array([5, 6, 7, 8, 1, 2, 3, 14, 15, 16])
Lengths = numpy.array([4, 3, 3])  
start = 0
end = 0
for i in range(len(Lengths)):
  end = end + Lengths[i]
  if i == 0:  ## Isolate the first scenario as splitting doesn't accept -1 as second argument. [end:-1:step] is not valid
    Values[0:end] = Values[end-1::-1]
  else:
    Values[start:end] = Values[end-1:start-1:-1]
  start = end
  print(Values)
  

Comments

0

You can build a list of indexes that reverse the positions relatively to each chunk's last index. Then use that as an indirection on the values array.

import numpy as np

values  = np.array([5, 6, 7, 8, 1, 2, 3, 14, 15, 16])
lengths = np.array([4, 3, 3])

s      = np.cumsum(lengths) - 1
s[1:] += s[:-1] + 1
i      = np.repeat(s, lengths) - np.arange(values.size)


print(values[i])    
# [ 8  7  6  5  3  2  1 16 15 14]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.