Pythonic方法在字符串中插入每2个元素

时间:2010-07-15 18:15:33

标签: python string

是否有一种pythonic方法将元素插入字符串中的每个第二个元素?

我有一个字符串:'aabbccdd',我希望最终结果为'aa-bb-cc-dd'。

我不确定如何做到这一点。

7 个答案:

答案 0 :(得分:39)

>>> s = 'aabbccdd'
>>> '-'.join(s[i:i+2] for i in range(0, len(s), 2))
'aa-bb-cc-dd'

答案 1 :(得分:37)

假设字符串的长度始终为偶数,

>>> s = '12345678'
>>> t = iter(s)
>>> '-'.join(a+b for a,b in zip(t, t))
'12-34-56-78'

t也可以用

消除
>>> '-'.join(a+b for a,b in zip(s[::2], s[1::2]))
'12-34-56-78'

算法是将字符串分组成对,然后将它们与-字符连接起来。

代码是这样写的。首先,它被分成奇数位和偶数位。

>>> s[::2], s[1::2]
('1357', '2468')

然后使用the zip function将它们组合成一个可迭代的元组。

>>> list( zip(s[::2], s[1::2]) )
[('1', '2'), ('3', '4'), ('5', '6'), ('7', '8')]

但是元组不是我们想要的。这应该是一个字符串列表。这是列表理解的目的

>>> [a+b for a,b in zip(s[::2], s[1::2])]
['12', '34', '56', '78']

最后,我们使用str.join()来组合列表。

>>> '-'.join(a+b for a,b in zip(s[::2], s[1::2]))
'12-34-56-78'

第一段代码是相同的想法,但如果字符串很长,则消耗更少的内存。

答案 2 :(得分:4)

如果你想保留最后一个字符,如果字符串有一个奇数长度,那么你可以修改KennyTM的答案以使用itertools.izip_longest

>>> s = "aabbccd"
>>> from itertools import izip_longest
>>> '-'.join(a+b for a,b in izip_longest(s[::2], s[1::2], fillvalue=""))
'aa-bb-cc-d'

>>> t = iter(s)
>>> '-'.join(a+b  for a,b in izip_longest(t, t, fillvalue=""))
'aa-bb-cc-d'

答案 3 :(得分:0)

这个单线程就可以了。如果你的字符串有奇数个字符,它将删除最后一个字符。

"-".join([''.join(item) for item in zip(mystring1[::2],mystring1[1::2])])

答案 4 :(得分:0)

这是一个列表理解方式,条件值取决于枚举模数,奇数最后一个字符将仅在组中:

for s  in ['aabbccdd','aabbccdde']:
    print(''.join([ char if not ind or ind % 2 else '-' + char
                    for ind,char in enumerate(s)
                    ]
                  )
          )
""" Output:
aa-bb-cc-dd
aa-bb-cc-dd-e
"""

答案 5 :(得分:0)

PEP8 states

对于形式为a += ba = a + b的语句,请不要依赖CPython有效地实现就地字符串连接。即使在CPython中,这种优化也很脆弱(仅适用于某些类型),并且在实现中根本不存在。

执行此操作的pythonic方式可以避免这种串联,并允许您连接字符串以外的可迭代对象,如下所示:

':'.join(f'{s[i:i+2]}' for i in range(0, len(s), 2))

另一种更类似于功能的方式可能是:

':'.join(map('{}{}'.format, *(s[::2], s[1::2]))) 

第二种方法具有仅连接成对字母的特殊功能(或错误)。所以:

>>> s = 'abcdefghij'
'ab:cd:ef:gh:ij'

和:

>>> s = 'abcdefghi'
'ab:cd:ef:gh'

答案 6 :(得分:0)

我倾向于使用正则表达式,因为它看起来不那么冗长,而且通常比所有替代方法都快。除了不得不面对有关正则表达式的传统知识外,我不确定是否存在缺点。

>>> s = 'aabbccdd'
>>> '-'.join(re.findall('..', s))
'aa-bb-cc-dd'

此版本对实际配对严格要求:

>>> t = s + 'e'
>>> '-'.join(re.findall('..', t)) 
'aa-bb-cc-dd'

...因此,通过调整,您可以容忍奇数长度的字符串:

>>> '-'.join(re.findall('..?', t))
'aa-bb-cc-dd-e'

通常您会多次执行此操作,因此可以提前创建快捷方式来抢先一步:

PAIRS = re.compile('..').findall

out = '-'.join(PAIRS(in))

或者我将在实际代码中使用什么:

def rejoined(src, sep='-', _split=re.compile('..').findall):
    return sep.join(_split(src))

>>> rejoined('aabbccdd', sep=':')
'aa:bb:cc:dd'

我不时使用类似的方法从6字节的二进制输入中创建MAC地址表示形式:

>>> addr = b'\xdc\xf7\x09\x11\xa0\x49'
>>> rejoined(addr[::-1].hex(), sep=':')
'49:a0:11:09:f7:dc'