将列表中的奇数和偶数移动到奇数和偶数位置

时间:2015-02-21 11:18:58

标签: python list python-3.x

我有一个奇数和偶数相等数量的列表。目标是修改列表以在奇数索引处具有奇数整数,在偶数索引处具有甚至整数。

这是我的方法:

我找出偶数索引和奇数索引的数字。然后找出偶数索引处的奇数和奇数索引处的偶数。最后交换错位的数字。

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

虽然它有效但我对解决方案不是很满意。对我的问题有更好的解决方案吗?我的目标是使x[][2, 3, 6, 5, 4, 7, 8, 9, 10, 11]一样可能以相同的奇偶格式排序。

5 个答案:

答案 0 :(得分:5)

创建列表的副本(仅用于创建等长的新列表),然后使用两个计数器来跟踪将偶数和奇数插入新列表的位置,将索引递增2每一次:

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

这比尝试就地交换一切要简单得多。

演示:

>>> 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]

对于排序输出(独立排序的赔率和均衡),只需对输入进行排序:

>>> 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]

答案 1 :(得分:2)

O(n**2)时间内将所有偶数项移至偶数索引,将所有奇数项转移到奇数索引:

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

如果赔率和赔率的数量不相等,代码可能会提升IndexError

示例:

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]

这是一个返回副本的线性解决方案:

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

示例:

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]

这是一个返回副本的线性单遍解决方案(它可能比以前的解决方案慢):

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]

示例:

L = fixed_odd_even_indices(map(int, sys.stdin)) # input one integer per line

答案 2 :(得分:1)

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]

答案 3 :(得分:1)

@MartijnPieters

解决方案的

itertools.count版本

>>> 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]

答案 4 :(得分:0)

虽然你选择了答案,但我想提交自己的方式。希望你喜欢它。

# 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