mchd
mchd

Reputation: 3163

Python doesn't let me modify a list passed as an argument

I am trying to work through a code signals challenge. Basically, I am given a list of integers. I am to sort the integers in an ascending order without changing the indexes of -1. So only the positive integers are sorted while the -1s stay where they are. To solve this, I decided to create a separate, sorted list of all the positive integers. Then, while iterating through the list, I replace each positive integer from the list passed as an argument with the new sorted list I've made.

Here is my code:

def sortByHeight(a):
    
    sorted_list = sorted([i for i in a if i > 0])
    count = 0
    
    for i in range(0, len(a)-1):
        if a[i] > 0:
            a[i] == sorted_list[count]
            count += 1
    
    return a

But when I return a, it seems as though the given list is completely unmodified. Here are some test cases:

Input: a: [-1, 150, 190, 170, -1, -1, 160, 180]
Output: [-1, 150, 190, 170, -1, -1, 160, 180]
Expected Output: [-1, 150, 160, 170, -1, -1, 180, 190]
Input: a: [2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1]
Output:[2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1]
Expected Output:[1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2]

While I appreciate all help, I am not looking for a quick fix or a long-winded explanation on using a different approach. I know that my approach is good and to help me learn, I would just like an explanation on what tweaks I need to make to this existing code.

Upvotes: 1

Views: 71

Answers (2)

superb rain
superb rain

Reputation: 5521

You got a proper answer already, let me just show another way to write the same approach which I think is not only nicer but also might've avoided those two bugs (not using indexed looping avoids getting the index limit wrong, and if you did a comparison here, you'd see booleans instead of no changes).

>>> it = iter(sorted(x for x in a if x > 0))
>>> [next(it) if x > 0 else x for x in a]
[-1, 150, 160, 170, -1, -1, 180, 190]

Or with a for-loop, but still using an iterator and using enumerate (also avoids the possibility of that index/limit bug):

it = iter(sorted(x for x in a if x > 0))
for i, x in enumerate(a):
    if x > 0:
        a[i] = next(it)

Upvotes: 0

ObsoleteAwareProduce
ObsoleteAwareProduce

Reputation: 756

I've compiled the comments on your OP into one code snippet:

def sortByHeight(a):

  sorted_list = sorted([i for i in a if i > 0])
  count = 0

  for i in range(0, len(a)):
    if a[i] > 0:
      a[i] = sorted_list[count]
      count += 1

  return a
  • There was a comparison operator (==) rather than an assignment operator (=) on line 8

you have to use = instead of == in line a[i] = sorted_list[count]

– furas

  • len(a) - 1 was the incorrect number, and should have been len(a) instead (line 6)

BTW: you have to use range(0, len(a)) without -1 - or shorter range(len(a))

– furas

Upvotes: 2

Related Questions