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

roo*_*oot 31 python string

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

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

我不确定我会怎么做.

ken*_*ytm 42

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

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

t也可以消除

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

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

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

>>> s[::2], s[1::2]
('1357', '2468')
Run Code Online (Sandbox Code Playgroud)

然后zip函数用于将它们组合成可迭代的元组.

>>> list( zip(s[::2], s[1::2]) )
[('1', '2'), ('3', '4'), ('5', '6'), ('7', '8')]
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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


Sil*_*ost 41

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

  • 我认为这比经过批准的答案中的拉链巫毒更加pythonic.事实上你不需要在python中使用for循环中的range(len(string)),这并不意味着必须去发明疯狂的东西才能避免它. (5认同)
  • 奇数长度的序列怎么样? (2认同)
  • @hamish:它保留最后一个字符并在其前面插入一个连字符.这不是一个理想的行为吗? (2认同)

Pet*_*sen 6

我倾向于依赖正则表达式来实现此目的,因为它看起来不那么冗长,并且通常比所有替代方案更快。除了必须面对有关正则表达式的传统观念之外,我不确定这是否有什么缺点。

>>> s = 'aabbccdd'
>>> '-'.join(re.findall('..', s))
'aa-bb-cc-dd'
Run Code Online (Sandbox Code Playgroud)

不过,这个版本对实际的对很严格:

>>> t = s + 'e'
>>> '-'.join(re.findall('..', t)) 
'aa-bb-cc-dd'
Run Code Online (Sandbox Code Playgroud)

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

>>> '-'.join(re.findall('..?', t))
'aa-bb-cc-dd-e'
Run Code Online (Sandbox Code Playgroud)

通常您会多次执行此操作,因此也许可以通过提前创建快捷方式来抢占先机:

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

out = '-'.join(PAIRS(in))
Run Code Online (Sandbox Code Playgroud)

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

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

>>> rejoined('aabbccdd', sep=':')
'aa:bb:cc:dd'
Run Code Online (Sandbox Code Playgroud)

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

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


Dav*_*rby 5

如果您想在字符串长度为奇数时保留最后一个字符,那么您可以修改 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'
Run Code Online (Sandbox Code Playgroud)

或者

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