Reputation: 255
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.
Upvotes: 1
Views: 13525
Reputation: 31
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]
Upvotes: 0
Reputation: 394
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
Upvotes: 0
Reputation: 414129
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
Upvotes: 2
Reputation: 133514
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]
Upvotes: 1
Reputation: 10408
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]
Upvotes: 1
Reputation: 1121446
Create a copy of the list (solely to create new list of equal length), then use two counters to track where to insert even and odd numbers into the new list, incrementing the indices by 2 each time:
def odd_even_sieve(x):
output = x[:]
even_index, odd_index = 0, 1
for value in x:
if value % 2 == 0:
output[even_index] = value
even_index += 2
else:
output[odd_index] = value
odd_index += 2
return output
This is far simpler than trying to swap everything in-place.
Demo:
>>> def odd_even_sieve(x):
... output = x[:]
... even_index, odd_index = 0, 1
... for value in x:
... if value % 2 == 0:
... output[even_index] = value
... even_index += 2
... else:
... output[odd_index] = value
... odd_index += 2
... return output
...
>>> odd_even_sieve([3, 2, 5, 6, 4, 7, 8, 9, 10, 11])
[2, 3, 6, 5, 4, 7, 8, 9, 10, 11]
>>> odd_even_sieve([19, 11, 23, 16, 18, 20])
[16, 19, 18, 11, 20, 23]
For sorted output (with odds and evens sorted independently), just sort the input:
>>> odd_even_sieve(sorted([3, 2, 5, 6, 4, 7, 8, 9, 10, 11]))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> odd_even_sieve(sorted([19, 11, 23, 16, 18, 20]))
[16, 11, 18, 19, 20, 23]
Upvotes: 5