2

I want to swap two lists, one is empty and the other is full.

I am trying to insert element by element, and within the same for loop to empty the second list, is it possible to be done with one for loop?

What I have managed so far is:

def swap():
    s1 = []
    s2 = [1,4,7]
    for i in range(0,len(s2)-1):
       s1.append(s2[i])
       s2.pop()

I know that it can be easily be done by:

def swap():
    s1 = []
    s2 = [1,4,7]
    s1 = s2
    s2 = []

It is for learning purposes

clubby789
  • 2,543
  • 4
  • 16
  • 32
newhere
  • 137
  • 8

6 Answers6

3

It is not recommended to update a list while looping over it.

Although, you can do this without even using a loop since Python assignations allows for swapping.

Note that you still will need to make a copy of l1 with l1[:] otherwise the content of l1 will be overwritten in the process.

def swap(l1, l2):
    l1[:], l2[:] = l2, l1[:]

l1 = [1, 2, 3]
l2 = []

swap(l1, l2)

print("l1: {}".format(l1)) # l1: []
print("l2: {}".format(l2)) # l2: [1, 2, 3]

The above code will work in the more general code where the second list is not empty.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
1
s1.append(s2[i])
s2.pop()

As pop() returns the popped value, this can be condensed to s1.append(s2.pop(i)).

Also, your second method will not work. s1 = s2 means that s1 and s2 reference the same list. Setting s2 to [] will also set s1 to [].

clubby789
  • 2,543
  • 4
  • 16
  • 32
1

The problem is that you refer to list you take items from, while you pop items from it. You are shortening it in the process, so you won't reach all the items it had initially.

You can do it like so:

while s2:
    s1.append(s2.pop(0))

pop(0), otherwise pop will take each time the last item and you will end up with a reversed list.

Comment: The easiest way to swap is s2, s1 = s1, s2

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
0

There's a few ways to do this. The most Pythonic is:

s1, s2 = s2, s1

That swaps which list each name points to. If you really need to move elements from one list to another, you can try a slice assignment:

s1[:] = s2[:]
s2.clear()
Michael Kolber
  • 1,309
  • 1
  • 14
  • 23
0

Let's say you have a function and you want to swap two lists in-place. Here's maybe how you'd do it:

def swap(l1, l2):
    # make it so that l1 is the smaller list, l2 is the bigger list
    if len(l2) < len(l1):
        l1, l2 = l2, l1
    # swap all shared elements
    for i in range(len(l1)):
        l1[i], l2[i] = l2[i], l1[i]
    # move all elements in l2 past the length of l1 to l1, one-by-one
    # do this by first recording the index of the first element in l2 that exceeds the length of l1
    # and continuously removing that index and adding it to l1 until we no longer can
    rmv_idx = len(l1)
    while len(l2) > rmv_idx:
        l1.append(l2.pop(rmv_idx))
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
0

The easiest way would probably be:

s1[:] = s2
del s2[:]

This works due to magic. In Python, you can get a range of a list (called a slice) by writing list_name[start_inclusive:end_exclusive]. Missing out the first number means "from the beginning" and missing out the second number means "to the end".

You can also assign to slices of lists. Guess what this will do:

a = [0, 1, 2]
a[1:2] = (3, 4)
print(a)

It prints [0, 3, 4, 2] because it replaces the middle value.

wizzwizz4
  • 6,140
  • 2
  • 26
  • 62