user2221325
user2221325

Reputation: 1

Permuting an Array in python

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

Answers (4)

user2221325
user2221325

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

user120242
user120242

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

JakobVinkas
JakobVinkas

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

D. Foley
D. Foley

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

Related Questions