0

I want to move the negative numbers to the end of the list until I encounter the positive number.

List:

a=[-1,-2,2,3,4,-5]

The result i want:

[-2, 2, 3, 4, -5, -1]
[2, 3, 4, -5, -1, -2]

My function:

def f1(A):
  for i in A:
    if i>=0:
      break
    if 'Z' not in globals() or 'Z' not in locals():
     X=A
     X1=X[0]
     X.remove(X1)
     X.append(X1)
     Z=X 
    else:
      X=Z
      X1=X[0]
      X.remove(X1)
      X.append(X1)
      Z=X
    print(Z)
 
a=[-1,-2,2,3,4,-5]
print (f1 (a))

But the result

[-2, 2, 3, 4, -5, -1]
None

can we solve it with this function?

  • Find the index of the first positive number, then `lst = lst[that_index:] + lst[:that_index]`, and Bob Martin's your uncle ;) – Jack Deeth Feb 13 '22 at 20:23
  • What's all this junk about `Z` and `X`? It looks like you're severely over-complicating this. – wjandrea Feb 13 '22 at 20:23
  • What are you actually asking? Obviously this function doesn't produce the desired result, so it can't be used to solve the problem. Do you want to ask *how to change this function* to get the desired result? Or would you be open to a totally different algorithm, like Jack suggested? You can [edit] to clarify. For more tips, see [ask]. – wjandrea Feb 13 '22 at 20:26
  • your code is right but your function doesn't return, just prints the list, so calling a print on it will first print the list (from inside the function) and then try to print the value of the return, which is not specified hence None. – Yvain Feb 13 '22 at 20:49
  • If there are only negatives, you want it to loop forever? – General Grievance Feb 18 '22 at 03:05

5 Answers5

1

It's not a for loop, but:

>>> def shift(lst):
...     while lst[0] < 0:
...         lst = lst[1:] + [lst[0]]
...     return lst
... 
>>> a
[-1, -2, 2, 3, 4, -5]
>>> b = shift(a)
>>> b
[2, 3, 4, -5, -1, -2]
Chris
  • 26,361
  • 5
  • 21
  • 42
0
while A[0] < 0: # While the list still begins with negative values
    A.append(A.pop(0)) # Rotate left

This should work. For the explanation look at the comments.


What's more your function f1 doesn't have a returned value, so:

print(f1(a))

doesn't produce any output (only None, since there's no returned value)


Since in Python the lists are "passed by reference", you can do something like this:

while A[0] < 0:
    ...
return A # The list is already edited in global scope BUT doing this you allow the print statement above
wjandrea
  • 28,235
  • 9
  • 60
  • 81
FLAK-ZOSO
  • 3,873
  • 4
  • 8
  • 28
  • 1
    Also, beside the point, but [conventionally, mutators return `None` in Python](/a/18829224/4518341). So I'd recommend either not returning `A`, or making a copy of `A` and returning that. – wjandrea Feb 13 '22 at 20:35
  • Yes, I knew this, but the OP wrote a print statement printing the returned value of the function, that's why I included the code. – FLAK-ZOSO Feb 13 '22 at 20:37
  • 1
    Ah, gotcha. Then I'd recommend simply removing the `print()`, and just do `f1(a)` – wjandrea Feb 13 '22 at 20:41
  • 2
    Please stop leaving comments along the lines of "I wrote an answer..." below the question. OP is notified already of new answers to their questions, your comments are unnecessary and simply add noise that makes work for moderators who clean them up. – user229044 Feb 13 '22 at 20:54
  • is while A[0]<0 modify A safe: Is there a defined behaviour here? – William Feb 13 '22 at 21:08
0
def f1(a): 
    a = a.copy() 
    while True: 
        i = a[0] 
        if i < 0: 
            a.append(i) 
            a = a[1:] 
            print(a) 
        else: 
            return a 
t1user
  • 48
  • 3
0

You asked to move the negative numbers to the end of the list a until encountering the first positive number. To actually move them in your list, meaning to "mutate" the list in place, you could do something like this:

def rotateInPlaceToFirstPositive(a):
    n = len(a)
    p = 0
    while p < n and a[p] < 0:
        p += 1
    if p < n:
        b = a[:p]
        for i in range(n - p):
            a[i] = a[i + p]
        for i in range(p):
            a[n - p + i] = b[i]

You can use this function like this:

a = [-1,-2,2,3,4,-5]
rotateInPlaceToFirstPositive(a)
print(a)
# prints: [2, 3, 4, -5, -1, -2]   

However, if you prefer to leave a unchanged and return a separate list that has the desired result, you can just do this:

def rotateToFirstPositive(a):
    n = len(a)
    p = 0
    while p < n and a[p] < 0:
        p += 1
    if p < n:
        a = a[p:] + a[:p]
    return a

Now, you will see this behavior when you call the function:

a = [-1,-2,2,3,4,-5]
print(rotateToFirstPositive(a))
# prints: [2, 3, 4, -5, -1, -2]   
constantstranger
  • 9,176
  • 2
  • 5
  • 19
0

You fell into one of python's traps. If A is a list and you do X=A, you do not get a new list, you just get a new name. Anything you do to list X will be done to list A and visa versa. So when you change list X you change list A which is the list you are looping over. Do not modify the thing you are looping over. To get a copy of a list use X=A.copy(). Now you can modify X without changing A.

William
  • 324
  • 1
  • 8