2017-06-20 109 views
0

为了正确格式化字符串,我被要求将其拆分成不同长度的块。将字符串拆分成不同长度的块

作为一个例子,这是一个字符串 - 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 

所以可以这样在更Python一个衬垫的方法呢?如果不是,其他更自动的方法是什么呢?

回答

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 
+1

感谢您的回答。输出是 - '--- 19f75e3f' – ShellRox

+0

现在输出结果是 - '--19f7-5e3' – ShellRox

+0

@ShellRox有点晚了,但是这里是一个没有itertools的1班轮。请注意,它是低效的,因为它不断调用总和。但它的工作。 –

4

递增地使用itertools.islice从字符串和切片一个迭代:

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)的总大小不等于的长度串;迭代器不完全耗尽。

您可以追加尾随部分(如果需要)在最终的预处理阶段:

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 
+0

感谢您的回答,如果没有itertools的帮助,它是正确的吗? – ShellRox

+0

@ShellRox任何不想使用itertools的原因? –

+0

Kolodoye我只是想避免额外使用模块,但如果没有其他简单的方法,那么这不是一个问题。 – ShellRox

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'] 
0

如果我们从列出的数据开始:

string = '25c319f75e3fbed5a9f0497750ea12992b30d565' 
lengths = [8, 4, 4, 12] 

我们可以用扫描发现ŧ他作beginnings或各部分的两端:

import itertools 
ends = list(itertools.accumulate(lengths)) 

看来accumulate是具体到Python 3,所以我们可能需要一种解决方法做扫描在Python 2(这一个在澳慢(N²)):

starts = [sum(lengths[:i]) for i in range(len(lengths))] 

,然后我们可以使用组合键提取部分:

dashed = '-'.join(string[end-length : end] 
        for end,length in zip(ends,lengths)) 

这一切的长度/索引操作的优点是它不会产生串的副本,只有它个别部分。否则,肖恩的解决方案非常整齐。

+0

感谢您的答案,绝对有用,但我试图找到解决方案,它只使用普通的python。 – ShellRox

+1

这是不是普通的Python?这都是标准库。 –

+0

对不起,误解,我的意思是我试图避免在这种情况下使用模块,因为它是可能的。 – ShellRox

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))