10

我有一个字符串,我需要将其分成 2 个字母的部分。例如,'ABCDXY'应该成为['AB', 'CD', 'XY']. 奇数字符情况下的行为可能完全是任意的(我会提前检查长度)。

有没有办法在没有丑陋的循环的情况下做到这一点?

4

6 回答 6

25
>>> [s[i:i + 2] for i in range(0, len(s), 2)]
['AB', 'CD', 'XY']
于 2012-09-19T09:06:38.853 回答
16

使用正则表达式!

>>> import re
>>> s = "ABCDXYv"
>>> re.findall(r'.{1,2}',s,re.DOTALL)
['AB', 'CD', 'XY', 'v']

我知道已经有一段时间了,但我又回到了这个问题上,很好奇哪种方法更好;我的:r'.{1,2}'或乔恩的r'..?'。从表面上看,乔恩的看起来好多了,我认为它会比我的快得多,但我惊讶地发现不是这样,所以我想我会分享:

>>> import timeit
>>> timeit.Timer("re.findall(r'.{1,2}', 'ABCDXYv')", setup='import re').repeat()
[1.9064299485802252, 1.8369554649334674, 1.8548105833383772]
>>> timeit.Timer("re.findall(r'..?', 'ABCDXYv')", setup='import re').repeat()
[1.9142223469651611, 1.8670038395145383, 1.85781945659771]

这表明确实r'.{1,2}'是更好/更快的选择。(但只是轻微)

于 2012-09-19T09:11:41.807 回答
2

你可以试试:

s = 'ABCDEFG'
r = [s[i:i+2] for i in xrange(0, len(s), 2)]

# r is ['AB', 'CD', 'EF', 'G']

更新 2

如果您不关心奇数字符,则可以使用正则表达式(避免循环):

s = 'ABCDEFG'
r = re.compile('(..)').findall(s)
# r is ['AB', 'CD', 'EF']
于 2012-09-19T09:07:20.863 回答
1

完美的 Pythonic 并没有什么丑陋之处:

string = 'ABCDXY'
[string[i:i+2] for i in xrange(0, len(string), 2)]

您还可以使用以下内容(来自 - http://docs.python.org/library/itertools.html):

def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

(这取决于您如何看待它 - 可能会或可能不会使用“循环”;))

或类似的东西:

re.findall('..?', string)
于 2012-09-19T09:07:46.853 回答
0

还有另一种解决方案,这个解决方案建立在zip一个切片步幅之上:

map(''.join, itertools.izip_longest(mystr[::2], mystr[1::2], fillvalue=''))

它确实处理奇数长度的输入。

于 2012-09-19T09:31:43.687 回答
0

这是另一个没有显式循环的解决方案(尽管@Emmanuel 的回答最适合您的问题):

s = 'abcdef'
L = zip(s[::2], s[1::2])
# -> [('a', 'b'), ('c', 'd'), ('e', 'f')]

获取字符串:

print map(''.join, L)
# ['ab', 'cd', 'ef']

list()在 Python 3上,必要时使用 wrap 。

于 2012-09-19T09:31:53.500 回答