将一个字符串分割成逐渐增长长度的子字符串块

3

假设我有这个字符串:

a = 'abcdefghijklmnopqrstuvwxyz'

我想将这个字符串分割成块,如下所示:

['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

为了使每个块具有不同数量的字符,您需要进行分块。例如,第一个块应该有一个字符,第二个块应该有两个字符,以此类推。
如果最后一块没有足够的字符,则需要添加空格,以匹配长度。
到目前为止,我尝试了以下代码:
print([a[i: i + i + 1] for i in range(len(a))])

但它输出的结果是:
['a', 'bc', 'cde', 'defg', 'efghi', 'fghijk', 'ghijklm', 'hijklmno', 'ijklmnopq', 'jklmnopqrs', 'klmnopqrstu', 'lmnopqrstuvw', 'mnopqrstuvwxy', 'nopqrstuvwxyz', 'opqrstuvwxyz', 'pqrstuvwxyz', 'qrstuvwxyz', 'rstuvwxyz', 'stuvwxyz', 'tuvwxyz', 'uvwxyz', 'vwxyz', 'wxyz', 'xyz', 'yz', 'z']

以下是我期望得到的输出:

['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

1
代码完全按照您的指示执行。您的算术有误。查找如何找到“三角形”数字,因为这些是您需要的值。 - Prune
@Prune 我也回答了。 - U13-Forward
7个回答

5
我认为没有任何一行代码或for循环可以像生成器那样优雅,因此让我们使用生成器:
from itertools import islice, count

def get_increasing_chunks(s):
    it = iter(s)
    c = count(1)

    nxt, c_ = next(it), next(c)
    while nxt:
        yield nxt.ljust(c_)
        nxt, c_ = ''.join(islice(it, c_+1)), next(c)

    return out

[*get_increasing_chunks(a)]
# ['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

4

感谢@Prune的评论,我设法找到了解决这个问题的方法:

a = 'abcdefghijklmnopqrstuvwxyz'
lst = []
c = 0
for i in range(1, len(a) + 1):
    c += i
    lst.append(c)
print([a[x: y] + ' ' * (i - len(a[x: y])) for i, (x, y) in enumerate(zip([0] + lst, lst), 1) if a[x: y]])    
    

输出:

['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

在列表推导式中找到三角数,如果长度不正确则添加空格。


3

所需的是一个数字来控制你要获取多少个字符(在这种情况下,是迭代的数量),还需要第二个数字来记住上次索引的位置,再加上一个最后的数字来告诉你何时停止。

my_str = "abcdefghijklmnopqrstuvwxyz"
last_index = 0
index = 1
iter_count = 1

while True:
    sub_string = my_str[last_index:index]
    print(sub_string)
    last_index = index
    iter_count += 1
    index = index + iter_count
    if last_index > len(my_str):
        break

请注意,您不需要使用while循环。我只是有些懒惰。

3

看起来 more_itertools 中的split_into 函数 可以帮助解决这个问题。虽然这种方法不如 @cs95 的答案 那样优雅,但也许能帮助其他人发现 itertools 模块 的实用性。

Yield a list of sequential items from iterable of length ‘n’ for each integer ‘n’ in sizes.

>>> list(split_into([1,2,3,4,5,6], [1,2,3]))
[[1], [2, 3], [4, 5, 6]]

要使用这个,我们需要构建一个sizes列表,例如[1, 2, 3, 3, 5, 6, 7]

import itertools

def split_into(iterable, sizes):
    it = iter(iterable)
    for size in sizes:
        if size is None:
            yield list(it)
            return
        else:
            yield list(itertools.islice(it, size))

a = 'abcdefghijklmnopqrstuvwxyz'

sizes = [1]
while sum(sizes) <= len(a):
    next_value = sizes[-1] + 1
    sizes.append(next_value)
# sizes = [1, 2, 3, 4, 5, 6, 7]

list(split_into(a, sizes))

# [['a'],
#  ['b', 'c'],
#  ['d', 'e', 'f'],
#  ['g', 'h', 'i', 'j'],
#  ['k', 'l', 'm', 'n', 'o'],
#  ['p', 'q', 'r', 's', 't', 'u'],
#  ['v', 'w', 'x', 'y', 'z']]

chunks = list(map("".join, split_into(a, sizes)))
# ['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz']

# Pad last item with whitespace.
chunks[-1] = chunks[-1].ljust(sizes[-1], " ")
# ['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

2
这是使用itertools中的accumulate函数的解决方案。
>>> from itertools import accumulate
>>> from string import ascii_lowercase

>>> s = ascii_lowercase
>>> n = 0
>>> accum = 0
>>> while accum < len(s):
    n += 1
    accum += n

>>> L = [s[j:i+j] for i, j in enumerate(accumulate(range(n)), 1)]

>>> L[-1] += ' ' * (n-len(L[-1]))
>>> L
['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

更新:也可以在 while 循环内获得。
n = 0
accum = 0
L = []
while accum < len(s):
    n += 1
    L.append(s[accum:accum+n])
    accum += n

['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz']

1

Adding a little to U11-Forward's answer:

a = 'abcdefghijklmnopqrstuvwxyz'
l = list(range(len(a))) # numberes list / 1 to len(a)
triangular = [sum(l[:i+2]) for i in l] # sum of 1, 2 and 1,2,3 and 1,2,3,4 and etc
print([a[x: y].ljust(i, ' ') for i, (x, y) in enumerate(zip([0] + triangular, triangular), 1) if a[x: y]])

输出:

['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz  ']

找出三角数,使用列表推导式,并在长度不正确时填充空格。

1
a = 'abcdefghijklmnopqrstuvwxyz'
inc = 0
output = []
for i in range(0, len(a)):
    print(a[inc: inc+i+1])
    inc = inc+i+1
    if inc > len(a):
        break
    output.append(a[inc: inc+i+1])        
        
print(output)

嘿,这是您所需输出的片段。我刚刚修改了您的逻辑。 输出:

['b', 'de', 'ghi', 'klmn', 'pqrst', 'vwxyz']

酷 +1 请注意,最后一个元素末尾应有两个空格。 - U13-Forward

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接