I have a bunch of lists that look like this one:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I want to swap elements as follows:
final_l = [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
The size of the lists may vary, but they will always contain an even number of elements.
I'm fairly new to Python and am currently doing it like this:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] final_l = [] for i in range(0, len(l)/2): final_l.append(l[2*i+1]) final_l.append(l[2*i])
I know this isn't really Pythonic and would like to use something more efficient. Maybe a list comprehension?
Store the element at pos1 and pos2 as a pair in a tuple variable, say get. Unpack those elements with pos2 and pos1 positions in that list. Now, both the positions in that list are swapped.
To swap two list elements x and y by value, get the index of their first occurrences using the list. index(x) and list. index(y) methods and assign the result to variables i and j , respectively. Then apply the multiple assignment expression lst[i], lst[j] = lst[j], lst[i] to swap the elements.
1. Using Collections. swap() method. The standard solution to swap two elements in a List is using the Collections.
swap() function in C++
No need for complicated logic, simply rearrange the list with slicing and step:
In [1]: l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] In [2]: l[::2], l[1::2] = l[1::2], l[::2] In [3]: l Out[3]: [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
Edited with explanation
I believe most viewers are already familiar with list slicing and multiple assignment. In case you don't I will try my best to explain what's going on (hope I do not make it worse).
To understand list slicing, here already has an excellent answer and explanation of list slice notation. Simply put:
a[start:end] # items start through end-1 a[start:] # items start through the rest of the array a[:end] # items from the beginning through end-1 a[:] # a copy of the whole array There is also the step value, which can be used with any of the above: a[start:end:step] # start through not past end, by step
Let's look at OP's requirements:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # list l ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 0 1 2 3 4 5 6 7 8 9 # respective index of the elements l[0] l[2] l[4] l[6] l[8] # first tier : start=0, step=2 l[1] l[3] l[5] l[7] l[9] # second tier: start=1, step=2 ----------------------------------------------------------------------- l[1] l[3] l[5] l[7] l[9] l[0] l[2] l[4] l[6] l[8] # desired output
First tier will be: l[::2] = [1, 3, 5, 7, 9]
Second tier will be: l[1::2] = [2, 4, 6, 8, 10]
As we want to re-assign first = second
& second = first
, we can use multiple assignment, and update the original list in place:
first , second = second , first
that is:
l[::2], l[1::2] = l[1::2], l[::2]
As a side note, to get a new list but not altering original l
, we can assign a new list from l
, and perform above, that is:
n = l[:] # assign n as a copy of l (without [:], n still points to l) n[::2], n[1::2] = n[1::2], n[::2]
Hopefully I do not confuse any of you with this added explanation. If it does, please help update mine and make it better :-)
Here a single list comprehension that does the trick:
In [1]: l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] In [2]: [l[i^1] for i in range(len(l))] Out[2]: [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
The key to understanding it is the following demonstration of how it permutes the list indices:
In [3]: [i^1 for i in range(10)] Out[3]: [1, 0, 3, 2, 5, 4, 7, 6, 9, 8]
The ^
is the exclusive or operator. All that i^1
does is flip the least-significant bit of i
, effectively swapping 0 with 1, 2 with 3 and so on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With