如何使用Python切换列表中每个元素的位置?

时间:2011-12-31 20:40:33

标签: python

使用Python,切换列表中每个其他元素的位置的最有效方法是什么?

例如,我试图在A切换后获得每个字母的字母顺序列表,如下所示:

import string
alphabet = string.ascii_uppercase
# ABCDEFGHIJKLMNOPQRSTUVWXYZ

switched_alphabet = do_something_magic(alphabet)
# ACBEDGF... 
# position 1, 3, 2, 5, 4, 7, 6... 

4 个答案:

答案 0 :(得分:6)

>>> import string
>>> alphabet = list(string.ascii_uppercase)
>>> for i in range(2, len(alphabet), 2):
...     alphabet[i], alphabet[i-1] = alphabet[i-1], alphabet[i]
... 
>>> alphabet
['A', 'C', 'B', 'E', 'D', 'G', 'F', 'I', 'H', 'K', 'J', 'M', 'L', 'O', 'N', 'Q', 'P', 'S', 'R', 'U', 'T', 'W', 'V', 'Y', 'X', 'Z']
>>> 

答案 1 :(得分:2)

另一种方法(使用切片并且比for循环快得多):

def switch(string, n=1):
    data = list(string)
    odd = -1 if (len(data)-n) % 2 else len(data)
    data[n:odd:2], data[n+1::2] = data[n+1::2], data[n:odd:2]
    return ''.join(data)

>>> switch(string.ascii_uppercase)
'ACBEDGFIHKJMLONQPSRUTWVYXZ'

n是您要保留的商品数量。有一个处理奇数长度字符串的技巧。

答案 2 :(得分:1)

以下是如何完成的

使用的工具

itertools.compress

itertools.izip

alphabet = string.ascii_uppercase
#The Even Series using itertools.compress
[x for x in itertools.compress(alphabet[1:],[0,1]*(len(alphabet)/2))]
['C', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'U', 'W', 'Y']
#The Odd Series
[x for x in itertools.compress(alphabet[1:],[1,0]*(len(alphabet)/2))]
['B', 'D', 'F', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', 'Z']
#Now Join it with itertools.izip
[''.join(x) for x in itertools.izip((x for x in itertools.compress(alphabet[1:],[0,1]*(len(alphabet)/2))),
                                        (x for x in itertools.compress(alphabet[1:],[1,0]*(len(alphabet)/2))))]
['CB', 'ED', 'GF', 'IH', 'KJ', 'ML', 'ON', 'QP', 'SR', 'UT', 'WV', 'YX']
#Finally Join as a Single String prefixing and 
#suffixing the first and the last character
alphabet[0]+''.join(''.join(x) for x in itertools.izip((x for x in itertools.compress(alphabet[1:],[0,1]*(len(alphabet)/2))),
                                                       (x for x in itertools.compress(alphabet[1:],[1,0]*(len(alphabet)/2)))))
           +alphabet[-1]
'ACBEDGFIHKJMLONQPSRUTWVYXZ'

所以最终的解决方案是

alphabet[0]+
    ''.join(''.join(x) for x in itertools.izip(
           itertools.compress(alphabet[1:],[0,1]*(len(alphabet)/2)),
           itertools.compress(alphabet[1:],[1,0]*(len(alphabet)/2))))
           +alphabet[-1]

注* *

正如@ J.F.Sebastian指出的那样,我们可以使用imap,这会简化上面的表达式

alphabet[0]+
"".join(itertools.imap("".join, itertools.izip(
           itertools.compress(alphabet[1:], itertools.cycle([0,1])), 
           itertools.compress(alphabet[1:], itertools.cycle([1,0]))))
           +alphabet[-1]

答案 3 :(得分:1)

内部索引:

''.join(alphabet[i + (-1)**(i%2==0)] for i in xrange(1, len(alphabet)-1))
# -> CBEDGFIHKJMLONQPSRUTWVYX

相同 - 使用itertools:

from itertools import cycle, izip

''.join(alphabet[i+j] for i,j in izip(xrange(1,len(alphabet)-1), cycle([1,-1])))

第一个和最后一个职位留作练习。