为了正确格式化字符串,我需要将其拆分为不同长度的块。
作为一个例子,这是一个字符串 - 25c319f75e3fbed5a9f0497750ea12992b30d565
,为了将它拆分成固定长度的块,我只需要使用步骤和切片:
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
n = 2
print("-".join([s[i:i+n] for i in range(0, len(s), n)]))
但是,如果n
是要拆分的数字列表,我该怎么办?例如:
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
n = [8, 4, 4, 4, 4, 12] # edited for consistency - Coldspeed
我做的唯一解决方案是:
print("-".join([s[0:8], s[8:12], s[12:16], s[16:20], s[20:24], s[24:32]]))
哪个不是pythonic,更不一定不可靠的字符串长度很大。
最后一个代码示例的输出:
25c319f7-5e3f-bed5-a9f0-4977-50ea1299
那么可以用更加pythonic的单线方式来完成吗?如果没有,还有什么其他更自动的方法可以完成?
答案 0 :(得分:5)
from itertools import islice
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
it = iter(s)
n = [8, 4, 4, 12]
s = '-'.join(''.join(islice(it, None, x)) for x in n)
print(s)
# 25c319f7-5e3f-bed5-a9f0497750ea
请注意,如果切片的总大小不等于字符串的长度,则字符串的尾部会丢失;迭代器并没有完全耗尽。
您可以在最终预处理阶段追加尾随部分(如果需要):
s += '-' + ''.join(it)
print(s)
# 25c319f7-5e3f-bed5-a9f0497750ea-12992b30d565
这是另一种使用for循环的方法,通过增加起始索引逐步切割字符串:
start = 0
d = []
for i in n:
d.append(s[start:start+i])
start += i
d.append(s[start:])
print('-'.join(d))
# 25c319f7-5e3f-bed5-a9f0497750ea-12992b30d565
答案 1 :(得分:1)
>>> s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
>>> n = [8, 4, 4, 4, 4, 12]
>>> print '-'.join([s[sum(n[:i]):sum(n[:i+1])] for i in range(len(n))])
输出
25c319f7-5e3f-bed5-a9f0-4977-50ea12992b30
答案 2 :(得分:1)
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
n = [8, 4, 4, 12]
def make_chunks(s,n):
result = []
for length in n:
result.append(s[:length])
s = s[length:]
if s:
result.append(s)
return '-'.join(result)
print(make_chunks(s,n))
答案 3 :(得分:0)
不是一个单线性的我害怕,但从我的头顶开始:
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
n = [8, 4, 4, 4, 4, 12]
res=[]
for split in n:
temp=s[:split]
s=s[split:]
res.append(temp)
print(res)
输出是一个数组,其中包含可以相应操作的相应字符串:
['25c319f7', '5e3f', 'bed5', 'a9f0', '4977', '50ea12992b30']
答案 4 :(得分:0)
如果我们从列出的数据开始:
string = '25c319f75e3fbed5a9f0497750ea12992b30d565'
lengths = [8, 4, 4, 12]
我们可以使用扫描来查找每个部分的开头或结尾:
import itertools
ends = list(itertools.accumulate(lengths))
似乎accumulate
特定于Python 3,因此我们可能需要一种解决方法来在Python 2中进行扫描(这一点在O(n²)处很慢):
starts = [sum(lengths[:i]) for i in range(len(lengths))]
然后我们可以使用该组合来提取部分:
dashed = '-'.join(string[end-length : end]
for end,length in zip(ends,lengths))
所有这些长度/索引操作的优点是它不会创建字符串的副本,只创建其各个部分。否则肖恩的解决方案非常整洁。
答案 5 :(得分:0)
如果已知可能的字符集并且每个块的大小是固定的,也可以使用正则表达式和capturing groups:
import re
s = '25c319f75e3fbed5a9f0497750ea12992b30d565'
n = [8, 4, 4, 4, 4, 12]
pattern = ''
for nchars in n:
pattern += f'([\w]{{{nchars}}})'
print(pattern)
# '([\\w]{8})([\\w]{4})([\\w]{4})([\\w]{4})([\\w]{4})([\\w]{12})'
pattern = re.compile(pattern, re.ASCII)
matches = pattern.search(s)
print(matches.groups())
# ('25c319f7', '5e3f', 'bed5', 'a9f0', '4977', '50ea12992b30')
print("-".join(matches.groups()))
# '25c319f7-5e3f-bed5-a9f0-4977-50ea12992b30'
正则表达式模式基本上是以下内容的重复模式:
([\\w]{n})
对于块大小列表中的每个 n
项,其中: