2

I know how to swap two variables together but I want to know if there is a quicker way to follow a certain pattern.

So I have this list of number. list=[1,2,3,4,5,6] And what I want to do is to swap a number with the following one and swap the next number with the number after it. so after swapping them it would become list=[2,1,4,3,6,3] So I was wondering if there was a way to be able to swap the numbers more simply. Thank you.

Mazdak
  • 105,000
  • 18
  • 159
  • 188
Winniez
  • 21
  • 2

4 Answers4

8
lst = [1,2,3,4,5,6] # As an example
for x in range(0, len(lst), 2):
    if x+1 == len(lst): # A fix for lists which have an odd-length
        break 
    lst[x], lst[x+1] = lst[x+1], lst[x]

This doesn't create a new list.

Edit: Tested and it's even faster than a list comprehension.

no_name
  • 742
  • 3
  • 10
  • Thanks a lot, this is a very easy method and if possible would you be able to explain what is going on. Thank you so much. – Winniez May 16 '15 at 10:31
  • This code basically swaps each two elements in the list, that's why I've provided a third argument to range(). The "If statement" Is necessary for odd-lengthed lists, as at one point the loop reaches the last element in the list and there isn't there an element next to it to perform the swapping, which part of the code you don't understand? – no_name May 16 '15 at 10:59
  • Yeah I understood that it swaps two elements together. for x in range(0, len(lst), 2): This is the part that I'm a bit confused about but that could be due to myself not knowing much about for loop. Thanks a lot for helping. – Winniez May 16 '15 at 11:19
  • And also about what the x+1 stands for? I'm sorry. I'm kinda new to python so there is a lot that I don't know yet. So thank you so much for your help. – Winniez May 16 '15 at 11:22
  • The list [1,2,3,4,5,6] has got 6 elements, so It has a length of 6, so range(0, len(lst), 2) == range(0, 6, 2) - I think you know what range(0,6) does, It returns a list which contains [0,1,2,3,4,5], range(0,6,2) does the same but it instead returns a list which contains [0, 2, 4], in other words it skips every other element thus returning half the number of elements in the original list – no_name May 16 '15 at 11:23
  • x +1 Is the next element in the list, simple as that, the "if" statement checks if there isn't a next element , If there isn't a next element then It breaks out of the loop (ends it). – no_name May 16 '15 at 11:27
  • I'd start the range at 1 and then swap elements x and x-1. Then you don't need the if+break. (Though for even-length lists I still prefer my solution, as it's significantly shorter and faster.) – Stefan Pochmann May 16 '15 at 13:06
  • @Stefan Pochmann I don't think that approach would work for even-lengthed lists, as for your solution, I don't think it is faster, it is a list comprehension which creates another list, I have made some tests with similiar piece of codes and found out that creating another list steals too much performance, but It's more readable and shorter. – no_name May 19 '15 at 11:29
  • @no_name Why would that not work for even lengths? It does. And that list comprehension *is* significantly faster, [have a look here](http://ideone.com/ZTruX0) for a test and its results (on the bottom of the page). – Stefan Pochmann May 19 '15 at 13:15
  • You're right, I was In hurry when I posted that comment. – no_name May 21 '15 at 11:06
2

If your list has even length, this might be the simplest way:

>>> lst = [1,2,3,4,5,6]
>>> [lst[i^1] for i in range(len(lst))]
[2, 1, 4, 3, 6, 5]
Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
1
from itertools import chain
from itertools import izip_longest

In [115]: li
Out[115]: [1, 2, 3, 4, 5, 6, 7]

In [116]: [i for i in list(chain(*(izip_longest(li[1::2],li[0::2])))) if i!=None]
Out[116]: [2, 1, 4, 3, 6, 5, 7]

or alternatively if you have even length list

a[start:end:step] # start through not past end, by step

Check this Understanding List slice notation

In [65]: li
Out[65]: [1, 2, 3, 4, 5, 6]

In [66]: new=[None]*(len(li))

In [71]: new[0::2]=li[1::2]

In [73]: new[1::2]=li[0::2]

In [74]: new
Out[74]: [2, 1, 4, 3, 6, 5]
Community
  • 1
  • 1
Ajay
  • 5,267
  • 2
  • 23
  • 30
  • Thanks a lot, this is a very easy method and if possible would you be able to explain what is going on. Thank you so much. – Winniez May 16 '15 at 10:45
1

My solution uses funcy

Example:

>>> from funcy import chunks, mapcat
>>> xs = [1, 2, 3, 4, 5, 6]
>>> ys = mapcat(reversed, chunks(2, xs))
>>> ys
[2, 1, 4, 3, 6, 5]

This kinds of reads nicely too; concatenate and map the results of reversing each 2-pair chunks of xs.

James Mills
  • 18,669
  • 3
  • 49
  • 62