2

I want to write a small code in python that Swap Elements in a list this program will accept a list, and will return a list that exchanges the positions of each pair of adjacent elements: positions 0 and 1, positions 2 and 3, and so on. If the list has an odd number of elements, then the element in the last position stays “in place”.

Before: [1,2,3,4,5]
After: [2,1,4,3,5]

This looks unpythonic. What is the Python way to do it?

JDB
  • 25,172
  • 5
  • 72
  • 123
  • 4
    What exactly is your question? This is neither a code-writing nor tutorial service. – jonrsharpe May 07 '15 at 09:52
  • Read up on how to write a good question that's [MCVE](http://stackoverflow.com/help/mcve). – SuperBiasedMan May 07 '15 at 09:53
  • 2
    "How do I ?" Plus some effort. See http://www.geeksforgeeks.org/pairwise-swap-elements-of-a-given-linked-list/ – Cees Timmerman May 07 '15 at 13:01
  • ...though highly popular questions appear to validate [a lack of shown effort](http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python?rq=1). Perhaps SO fears answers not being accepted or useful enough (a little personal info about what you need it for would help) but that's not the reason why this question is on hold. – Cees Timmerman May 07 '15 at 14:31
  • Sure, Cees's answer seems like a perfect fit for this question. – alexis May 08 '15 at 19:37
  • @CeesTimmerman - This question has been reopened. Feel free to move your answer to SO if you feel like it. – JDB May 08 '15 at 21:58

10 Answers10

5

Most pythonic way:

def swappairwise(a):
  l = len(a)&~1
  a[1:l:2],a[:l:2] = a[:l:2],a[1:l:2]
Arpegius
  • 5,817
  • 38
  • 53
  • I don't understand `&-` but your code works and is 50+ chars shorter than mine. – Cees Timmerman May 08 '15 at 23:04
  • @CeesTimmerman Its binary `and` with all 1 except first, to round down to even number. – Arpegius May 08 '15 at 23:33
  • I guessed as much, but thought the negative sign was a single bit. [I was wrong.](http://www.c4learn.com/c-programming/c-bitwise-shift-negative-number/) – Cees Timmerman May 09 '15 at 12:36
  • 1
    ...provided the hardware uses [two's complement notation](http://en.wikipedia.org/wiki/Two%27s_complement) and 2 is not a [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point) floating point value. I'd use `&~1` instead of `&-2`. – Cees Timmerman May 09 '15 at 16:49
4

Here is a neat one, if you are always guaranteed to have even numbers:

 nums = [1,2,3,4,5,6]
 print([nums[i^1] for i in range(len(nums))])
 >>[2, 1, 4, 3, 6, 5] 

Explanation:

print (0^1)    #1
print (1^1)    #0
print (2^1)    #3
print (3^1)    #2
print (4^1)    #5
print (5^1)    #4

As a refresher, the XOR has the following effect:

A   B | Output
---------------
0   0     0
0   1     1
1   0     1
1   1     0

And the official description: Each bit of the output is the same as the corresponding bit in x if that bit in y is 0, and it's the complement of the bit in x if that bit in y is 1.

user1767754
  • 23,311
  • 18
  • 141
  • 164
2

Building on the answer above from @Arpegius, here a, hopefully, somewhat more readable solution. Uses the same approach.

def swap_list_pairwise(lis):
    """Pairwise swap of all elements in a list.

    If the number of elements is odd, the leftover element
    stays at its place.
    """
    length = len(lis)  
    # Stop at second last if length is odd, otherwise use full list. 
    end = length - 1 if length % 2 else length
    lis[1:end:2], lis[:end:2] = lis[:end:2], lis[1:end:2]
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
0

If you want "pythonic", try "How do you split a list into evenly sized chunks in Python?", followed by a map() that reverses every chunk. May not be too performant, though.

(Oh, forgot the flattening of the list at the end)

Community
  • 1
  • 1
0

Here is a way:

def pairwise_swap(iterable):
    for i, value in enumerate(iterable):
        if i % 2 == 0:
            saved = value
        else:
            yield value
            yield saved

>>> list(pairwise_swap(range(10)))
[1, 0, 3, 2, 5, 4, 7, 6, 9, 8]
Alok Singhal
  • 93,253
  • 21
  • 125
  • 158
  • 2
    This swallows the last element if the number of elements in the iterable is odd. I modified your solution a bit. See my answer. – Mike Müller May 09 '15 at 13:50
0

Nice approach by @Alok above. This should fix the missing last element if the number of elements is odd.

def pairwise_swap(iterable):
    """Pairwise swap of all elements in an iterable.

    If the number of elements is odd, the leftover element
    stays at its place.
    """
    for i, value in enumerate(iterable):
        if i % 2 == 0:
            saved = value
        else:
            yield value
            yield saved
    # Don't forget the last element if `iterable` has an odd 
    # number of elements. Since counting starts a zero, we need 
    # to test if `i` is even. 
    if iterable and i % 2 == 0:
        yield value
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • This should've been an edit or comment on Alok's answer. – Cees Timmerman May 09 '15 at 16:53
  • @Cees I added a comment at Alok’s answer as well. I tried to put my additions there first. But the code seemed rather difficult to read. Therefore I decided to reference the original in a new answer. – Mike Müller May 09 '15 at 20:25
0

How about trying this one out?

>>> l = [1,2,3,4,5,6]
>>> pl = [l[i:i+2] for i in range(0,len(l),2)]
>>> pl
[[1, 2], [3, 4], [5, 6]]
>>> for i in pl:
...     i[0],i[1] = i[1],i[0]
...     print i
... 
[2, 1]
[4, 3]
[6, 5]
>>> pl
[[2, 1], [4, 3], [6, 5]]
>>> 
>>> zpl = [i for sublist in pl for i in sublist]
>>> zpl
[2, 1, 4, 3, 6, 5]
>>> 

I tried to resolve in the easiest way out.

Rahul
  • 2,580
  • 1
  • 20
  • 24
0
It will work for both even and odd elements. if list elements are even 
first part will work if not else will do his task.

a = list(input("Put your list here: "))
len_a = len(a)
last_element = len_a-1

result = 0
if len_a % 2==0:
        for i in range(0, len(a), 2):
                a[i], a[i + 1] = a[i + 1], a[i]
        print("its if",a)

else:
        a_n = a.pop()
        for i in range(0, len(a), 2):
                a[i], a[i + 1] = a[i + 1], a[i]
        a.insert(0,a_n)
        # a.insert(last_element,a_n) if you want last element remain unmodified
        print("its else:",a)
Md Hasnat
  • 1
  • 2
0

This is what worked for me. Hopefully, it can help others. I think about using boxes. The value in the first position needs a temporary place to be before it can be swapped, so I assign it to x and then make the swap. Incrementing by 2 will skip over the last element, so it's okay with odd-numbered lists as well.

a = [int(s) for s in input().split()]
i = 0
while i in range(0, len(a) - 1):
    x = a[i]
    a[i] = a[i + 1]
    a[i + 1] = x
    i += 2
print(a)
Marnie
  • 1
-1

Found this to be much simpler solution and handels the list with odd elements

elements = list(map(int,input().split()))
swap = []

i = 0
while i < len(elements):
    if i+1 < len(elements):
        swap.append(elements[i+1])
        swap.append(elements[i]) 
    else:
        swap.append(elements[-1])
    i = i+2
print(swap)