'Move odd and even numbers in list to odd and even positions
I have a list with an equal number of odd and even integers. The goal is to modify the list to have odd integers at odd indices and even integers at the even indices.
Here is my approach:
I find out the numbers at even indexes and odd indexes. Then find out odd numbers at even indexes and even numbers at odd indexes. Finally swap the misplaced numbers.
x = [3, 2, 5, 6, 4, 7, 8, 9, 10, 11]
even_pos = []
odd_pos = []
for i in range(len(x)):
if x[i] % 2 == 0:
even_pos.append(i)
else:
odd_pos.append(i)
even_pos_with_odd = []
odd_pos_with_even = []
for j in range(len(even_pos)):
if even_pos[j] % 2 != 0:
even_pos_with_odd.append(j)
if odd_pos[j] % 2 == 0:
odd_pos_with_even.append(j)
for n in range(len(even_pos_with_odd)):
temp = x[odd_pos[odd_pos_with_even[n]]]
x[odd_pos[odd_pos_with_even[n]]] = x[even_pos[even_pos_with_odd[n]]]
x[even_pos[even_pos_with_odd[n]]] = temp
I am not very happy with the solution though it works. Is there any better efficient solution to my problem? My aim was to make x[]
like [2, 3, 6, 5, 4, 7, 8, 9, 10, 11]
possibly sorted in the same odd-even format.
Solution 1:[1]
To move all even items to even indices and all odd items to odd indices inplace in O(n**2)
time:
def fix_odd_even_indices(lst):
for i in range(len(lst)):
j = i
while i & 1 != lst[i] & 1: # element is in the wrong place
j += 1
lst[i], lst[j] = lst[j], lst[i] # swap
The code may raise IndexError
if the number of odds and evens is unequal.
Example:
lst = [3, 2, 5, 6, 4, 7, 8, 9, 10, 11]
fix_odd_even_indices(lst)
print(lst)
# -> [2, 3, 6, 5, 4, 7, 8, 9, 10, 11]
Here's a linear solution that returns a copy:
def fixed_odd_even_indices(seq):
L = [None]*len(seq)
L[1::2] = [x for x in seq if x & 1] # odd
L[::2] = [x for x in seq if not x & 1] # even
return L
Example:
print(fixed_odd_even_indices([3, 2, 5, 6, 4, 7, 8, 9, 10, 11]))
# -> [2, 3, 6, 5, 4, 7, 8, 9, 10, 11]
Here's a linear single-pass solution that returns a copy (it is probably slower than the previous solution):
def fixed_odd_even_indices(iterable):
odds, evens = [], []
for x in iterable:
(odds if x & 1 else evens).append(x)
return [x for pair in zip(evens, odds) for x in pair]
Example:
L = fixed_odd_even_indices(map(int, sys.stdin)) # input one integer per line
Solution 2:[2]
def odd_even(x):
odds = sorted(filter(lambda n: n % 2 == 1, x))
evens = sorted(filter(lambda n: n % 2 == 0, x))
pairList = zip(odds, evens)
return [n for t in pairList for n in t]
Solution 3:[3]
itertools.count
version of the solution by @MartijnPieters
>>> from itertools import count
>>> x = [3, 2, 5, 6, 4, 7, 8, 9, 10, 11]
>>> def odd_even_sieve(x):
output = x[:]
a, b = count(0, 2), count(1, 2)
for value in x:
output[next(a if value % 2 == 0 else b)] = value
return output
>>> odd_even_sieve(x)
[2, 3, 6, 5, 4, 7, 8, 9, 10, 11]
Solution 4:[4]
Though you have chosen your answer, but I'd like to submit my way. Hope you may like it.
# Using python 2.7
First_list = [1,3,5,7,2,4,6,8] #equal no. of even and odd numbers
temp_odd = [x for x in First_list if x%2 ==1]
temp_even = [x for x in First_list if x%2 ==0]
First_list[0::2] = temp_even # as we know,0 is even index,followed by 2,4...
First_list[1::2] = temp_odd # similarly starting with index 1, odd indices
# are 3,5 ...
# we can write sorted(temp_odd) like that
print First_list
Solution 5:[5]
If someone is looking for a function to flip the odd and even indices of an array, he/she can use this one:
import numpy as np
def flip(x):
'''x must be an array'''
flipped=[]
for i in range(int(len(x)/2)):
flipped.append(x[(i+1)*2-1])
flipped.append(x[i*2])
flipped=np.array(flipped)
return flipped
>>> print(x)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
>>> print(flip(x))
[ 1 0 3 2 5 4 7 6 9 8 11 10 13 12 15 14 17 16 19 18]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | jamylak |
Solution 4 | SamCodes |
Solution 5 |