Reputation: 1
I am trying to permute an array based on values from another array. A = [5, 6, 7, 8] P = [1, 3 ,2, 0] Should return [6, 8, 7, 5]
I have the below code written in python. I wanted to see if this is an acceptable approach to this problem or if there are better ways to solve this problem
def permute(A, P):
for i in range(len(P)):
if i != P[i]:
if int(P[P[i]]) >= 0:
if A[i]>0:
A[i], P[i]=A[P[i]], -A[i]
else:
A[i], P[i] = A[P[i]], f"{A[i]}"
else:
if isinstance(P[P[i]],int):
A[i], P[i] = -P[P[i]], -A[i]
else:
A[i], P[i] = int(P[P[i]]), f"{A[i]}"
return(A)
I store the original value from A as a negative value in P so i can retrieve it back by changing the sign. However I am doing a string convert if the value in the original array is negative to keep a track of when the values are negative vs when i store them as negative in P.
This code works but looking for ideas on if this can be done in a much cleaner way
Upvotes: 0
Views: 898
Reputation: 1
I think i should have mentioned this earlier, the solutions is to update list in place and so i cannot do prints. But i was able to come up with a better algorithm to update without changing signs or string convert
def permute(A, P):
for i in range(len(P)):
if i != P[i]:
if P[i] >= i:
A[i], P[i]=A[P[i]], A[i]
else:
A[i], P[i] = P[P[i]]
return P
Upvotes: 0
Reputation: 15268
In-place copying, using P to track original values. Copies original values swapped to P. If index value in P already iterated over, use P, else use value in A (to check if it has been overwritten yet).
A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]
for i,p in enumerate(P):
P[i]=A[i]
A[i]=P[p] if p < i else A[p]
It would have been even simpler to just copy values to P directly if you need in-place without creating a list (slightly more efficient in both time and space as well), and use P as the new A, but it seems like you want to do it in-place on A for some reason, and only use P as a temporary store.
List comprehension is also simpler to implement, and creates a copy without mutating the lists.
Difference in efficiency shouldn't ever really matter. Even if you're dealing with extremely large lists in resource constrained situations, it's not likely to ever be a noticeable difference, let alone be the bottleneck.
Upvotes: 1
Reputation: 1063
Seems straigt forward to use list comprihension:
A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]
print([A[i] for i in P ])
Also, if you use a numpy array istead, you can simply use the P
array as indexing for the new list:
import numpy as np
A = np.array([5, 6, 7, 8])
P = [1, 3 ,2, 0]
print(A[P])
Also giving the correct answer.
Upvotes: 0
Reputation: 1024
If I understand correctly, isn't this what you want?
A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]
for i in range(len(P)):
print(A[P[i]])
Upvotes: 0