-4

I have to create a code(function) that moves elements in a list without using temporary list and the function has to return nothing, I've tried the following but It won't work please help

def move_zeros_v2(lst):
    left = []
    right = []
    left_a = left.append
    right_a = right.append
    for x in lst:
        if x:
            left_a(x)
        else:
            right_a(x)
    left.extend(right)
    i = 0
    while i < len(left):
        lst[i] = left[i]
        i = i + 1

x = [1, 0, 3, 0, 0, 5, 7]
z=move_zeros_v2(x)
print(x, z)
martineau
  • 119,623
  • 25
  • 170
  • 301
Patick
  • 1
  • 1
  • 1
  • 1
    "It won't work" doesn't tell us much without giving us what it *does* do. Is there an error? What's the (incorrect) output? For that matter what does the CORRECT output look like? – Adam Smith Nov 03 '15 at 19:29
  • Questions seeking debugging help (**"why isn't this code working?"**) must include the desired behavior, *a specific problem or error* and *the shortest code necessary* to reproduce it **in the question itself**. Questions without **a clear problem statement** are not useful to other readers. See: [How to create a Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – MattDMo Nov 03 '15 at 19:32
  • your function does not return anything... Other than that, it works. – njzk2 Nov 03 '15 at 19:38
  • so, define `It won't work` – njzk2 Nov 03 '15 at 19:39
  • We could really use an example of correct output here. These requirements are vague enough to satisfy by simply removing anything that isn't a zero. – candied_orange Nov 03 '15 at 19:49

5 Answers5

5

Here is one way to do it:

def move_zeros(lst):
  n = len(lst)
  lst[:] = filter(None, lst)
  lst.extend([0] * (n - len(lst)))
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • does `filter(None` remove zeroes, too? I've only ever used it to drop literal `None`s from a sequence – Adam Smith Nov 03 '15 at 19:35
  • @AdamSmith: It does: https://docs.python.org/3/library/functions.html#filter – NPE Nov 03 '15 at 19:37
  • Awesome! Pedantically: this actually *removes* all zeroes, then adds an equal amount to the end of the list, but that's neither here nor there. – Adam Smith Nov 03 '15 at 19:38
0

The big "gotcha" here is "no temporary list." This means that the usual approach of iterating over a copy of the list while mutating the real list...

for idx, el in enumerate(lst[:]):

...violates the rules of the assignment. Instead you'll have to do some jiggery pokery with indexes and etc.

for idx in range(len(lst)):
    el = lst[idx]
    while el == 0:
        # push the zero to the end of the list
        lst.append(lst.pop(idx))
        el = lst[idx]  # check if the next one is a zero as well!

This is generally a Bad Idea, and definitely code smell in Python. You shouldn't feel bad about using a temporary list if this were Real Code, but I assume it's a homework assignment.

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
0

This is very easy to do with normal list methods, although this isn't necessarily the prettiest or most efficient way to accomplish your task.

Take some regular list of integers with some zeroes sprinkled in:

test_list = [1, 2, 4, 0, 3, 5, 0, 9, 0, 3, 4, 7]

Figure out how many zeroes there are. You'll be sticking these on the end later:

zeroes_to_append = test_list._____(0)

You can remove the original zeroes with a simple loop. This method will cause a (catchable) ValueError when you run out of zeroes to get rid of:

>>> while True:
...   try:
...     test_list.______(0)
...   except ValueError:
...     break

Then you put the number of zeroes you removed back on the right end:

for i in range(zeroes_to_append):
    test_list.append(0)

The only thing left for you is to complete your homework by looking up the actual methods I used in order to "fill in the blanks" in this answer. Use this page in the Python docs as a reference to help!

Two-Bit Alchemist
  • 17,966
  • 6
  • 47
  • 82
0

Not a very efficient solution, but I think, that's the type of solution you need.

x = [1, 0, 3, 0, 0, 5, 7]
for _ in range(len(x)-1):
    for index in range(len(x)-1):
        if x[index]==0:
            x[index+1],x[index]=x[index],x[index+1]

print x

Output:

[1, 3, 5, 7, 0, 0, 0]
Ahsanul Haque
  • 10,676
  • 4
  • 41
  • 57
  • nice bubblesort. Since you don't use the `i` you should name it `_`, and since it's just `else: pass` you can omit that entirely. – Adam Smith Nov 03 '15 at 20:00
  • 1
    Actually, user1749431's answer that involved sorting make me think that I can mimic bubble sort to solve the problem. Thanks for your suggestion. – Ahsanul Haque Nov 03 '15 at 20:02
-5

Updated answer with a solution for same list;

lst = filter(lambda x: x!=0, lst) + lst[:]

#which returns [1, -1, 5, 7, 0, 0, 0] for lst = [1, 0,-1, 0, 0, 5, 7]

You can use a listcomprehension with sorted() and reversed()

x = [1, 0, 3, 0, 0, 5, 7]
sorted_x = [i for i in reversed(sorted(x))]

# will return [7, 5, 3, 1, 0, 0, 0]
user1749431
  • 559
  • 6
  • 21
  • why list comp it? `list(reversed(sorted(x)))` – Adam Smith Nov 03 '15 at 19:31
  • `[1, 3, 5, 7,0,0,0]` is the right answer, not `[7, 5, 3, 1, 0, 0, 0]` – Ahsanul Haque Nov 03 '15 at 19:33
  • The OP also has specific constraints – Padraic Cunningham Nov 03 '15 at 19:34
  • Using a list comprehension is also "using temporary list". – martineau Nov 03 '15 at 19:34
  • That's the same thing with a little less code, I think listcomprehensions are more pedagogical when learning loops. – user1749431 Nov 03 '15 at 19:35
  • @AhsanulHaque and how do you know the right answer? – candied_orange Nov 03 '15 at 19:35
  • 1
    That's because, **How to move zeros to the end of a list** is the title – Ahsanul Haque Nov 03 '15 at 19:36
  • [1, 3, 5, 7,0,0,0] - as I understood it should be the zeros in the end, neither this [i for i in reversed(sorted(x))] nor this list(reversed(sorted(x))) will return [1, 3, 5, 7,0,0,0] since it reverses the order from low-> high to high -> low – user1749431 Nov 03 '15 at 19:37
  • @AhsanulHaque that is insufficient. That does not require us to only move the zeros. It doesn't even specify which end of the list. – candied_orange Nov 03 '15 at 19:38
  • 1
    Arguments about the contents of the question should be addressed in the comments *on the question*. This answer is wrong not because the question is unclear, but because it doesn't respect the *clear* part of the question ("No temporary list") – Adam Smith Nov 03 '15 at 19:39
  • not sure that I get your comment @AhsanulHaque, if list [1, 0, 3, 0, 0, 5, 7] is to be returned with the zeros in the end then sorted() and reversed() are common python functions to use. – user1749431 Nov 03 '15 at 19:40
  • @user1749431: it's true your method puts the zeros at the end, but (1) `sorted` creates a temporary list, (2) the listcomp creates a separate temporary list, and (3) you change the order of the nonzero values, not simply move the zeros to the end. – DSM Nov 03 '15 at 19:43
  • As far as I understand, OP needs the same list except zeros at the end which yields `[1, 3, 5, 7,0,0,0]` as the right answer to me. After all these discussions, it's wise to wait until OP clarifies it. (I didn't downvote you) – Ahsanul Haque Nov 03 '15 at 19:44
  • a function taking "lst" is also taking "any list" so I'm not sure what your assignment defines as list but all the solutions above include a temporary list variable – user1749431 Nov 03 '15 at 19:46
  • 1
    the OP never mentioned anything about sorting. Just moving the 0s at the end. – njzk2 Nov 03 '15 at 19:47
  • the sorted and reversed takes the list x as you defined and returns it as sorted and reversed. – user1749431 Nov 03 '15 at 19:48
  • the Python way of "moving things to the end" is by sorting the list. This is far simpler than looping. – user1749431 Nov 03 '15 at 19:50
  • 2
    @user1749431 both `sorted` and `reversed` return a ***new*** list, which is why you're getting so much flak. You also don't seem to understand the difference between a list in memory and a reference to that list inside a function. I agree that the assignment is asking them to do something stupid, but at least be forthright that you're failing the assignment to write better code. – Adam Smith Nov 03 '15 at 19:55
  • @user1749431: your approach will never generate output where the nonzero values aren't in descending order. Your approach will also turn `[-1,0,1]` into, er, `[1,0,-1]`, and not push the 0s to the end at all. Now as it happens you *can* push the zeros to the end using a sort, but not the way you've done here. – DSM Nov 03 '15 at 19:56
  • you're right on that on second thought, I focused on the moving part. I'll see if I can come up with something else. – user1749431 Nov 03 '15 at 19:57
  • DSM, it returns [7, 5, 3, 2, 1, 0, 0] for [1, 2, 3, 0, 0, 5, 7] so not the issue here, but I can agree that it creates a new list – user1749431 Nov 03 '15 at 20:01
  • @user1749431: I flipped the signs in my comment (now fixed), but the fact that you change the order of the original nonzero values remains. – DSM Nov 03 '15 at 20:03
  • true, it would only work on positive integers – user1749431 Nov 03 '15 at 20:06
  • 1
    updated with a same list solution that seems to meet the same list condition and negative integers, similar to the above but with a oneliner – user1749431 Nov 03 '15 at 20:39