3

I have a list of 4 items like this:

a, b, c, d = [1, 2, 3, 4]

I'm reordering the list, flipping each pair:

[b, a, d, c]

Is there a way to do this in one expression? I've tried using list comprehension and unpacking, but can't seem to get it right.

I have [1, 2, 3, 4]. I'm trying to get [2, 1, 4, 3].

nathancahill
  • 10,452
  • 9
  • 51
  • 91

8 Answers8

8

More generically, if you're looking to flip pairs of numbers in a list:

>>> L = [1, 2, 3, 4, 5, 6]
>>> from itertools import chain
>>> list(chain.from_iterable(zip(L[1::2], L[::2])))
[2, 1, 4, 3, 6, 5]
jterrace
  • 64,866
  • 22
  • 157
  • 202
5

Look at this:

>>> lst = [1, 2, 3, 4]
>>> [y for x in zip(*[iter(lst)]*2) for y in x[::-1]]
[2, 1, 4, 3]
>>>
>>> lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [y for x in zip(*[iter(lst)]*2) for y in x[::-1]]
[2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
>>>
  • Slick. Going to have to spend some time figuring out how this works. – nathancahill Nov 01 '13 at 22:17
  • @nathancahill - Thank you. I assume you understand the list comprehension parts. What I did with `zip` and `iter` is a very helpful trick you should memorize (it's used a lot and will _really_ help you). Here is a reference on it: http://stackoverflow.com/questions/18541215/how-do-you-access-a-list-in-group-of-3-in-python Scroll down to @abarnert's answer. –  Nov 01 '13 at 22:25
2

If this is only about 4 member lists - this would suffice:

list = [1, 2, 3, 4]
reordered_list = [list[1], list[0], list[3],list[2]]
Artur
  • 7,038
  • 2
  • 25
  • 39
1

Because absolutely nobody has given an answer that works on generic iterables,

from itertools import chain

items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

zip(*[iter(items)]*2)
#>>> <zip object at 0x7fd673afd050>

[itms for itms in zip(*[iter(items)]*2)]
#>>> [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

So zip(*[iter(x)]*2) means ix = iter(x); zip(ix, ix) which pairs each element.

Then you can reverse:

[(y, x) for (x, y) in zip(*[iter(items)]*2)]
#>>> [(2, 1), (4, 3), (6, 5), (8, 7), (10, 9)]

Putting it all together and flattening:

[itm for (x, y) in zip(*[iter(items)]*2) for itm in (y, x)]
#>>> [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]

It's generic and short!


If you want something faster at the expense of genericism, you'll be hard pressed to better this:

new = list(items)
new[::2], new[1::2] = new[1::2], new[::2]

new
#>>> [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]

Note that this still works on arbitrary iterables, but there are fewer layers of abstraction; you can't bump up the size of the flipped sub-lists as easily and can't output iterables, etc.

Veedrac
  • 58,273
  • 15
  • 112
  • 169
0

Do you mean this:

>>> a, b, c, d = [1, 2, 3, 4]
>>> b, a, d, c = a, b, c, d
>>> a
2
>>> b
1
>>> c
4
>>> d
3

?

NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

Try this list comprenhension solution:

a = [1,2,3,4,5,6] # Any list with even number of elements
b = [a[e+1] if (e%2 == 0) else a[e-1] for e in range(len(a))]

This just works if the list a have an even number of elements.

Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
0
In [1]: l = [1, 2, 3, 4]

In [2]: list(chain(*map(reversed, zip(l[::2], l[1::2]))))
Out[2]: [2, 1, 4, 3]
utdemir
  • 26,532
  • 10
  • 62
  • 81
0

Am I missing something? Reorder given_list with a loop:

rez = []
for i in range(len(given_list)-1, -1, -1):
    rez.append(given_list[i])
return rez
A S
  • 1,195
  • 2
  • 12
  • 26