索引列表切片字符串。

4

我有一个长度列表存在于一个列表中,例如:

a = [1, 3, 4]

此外,我有一个字符串,其长度恰好是a(这里是8)的数字之和,看起来像这样:

s = "01100110"

我正在遍历a的长度,并且每次我想要在a中准确地包含接下来的n个比特。

在这里,它将运行三次,给出"0","110"和"0110"。

是否有非常聪明的方法可以高效地完成这个操作,例如通过切片? 我脑海中有一些奇怪而复杂的方法,但寻找更有效的解决方案。

我想到了一些解决方案:

counter_index = 0
counter_sum = 0

for i in range(len(a)):
   res = s[counter_sum:counter_sum+a[counter_index]
   counter_sum += a[counter_index]
   counter_index += 1
   print(res)

3
你能分享你现有的代码吗? - balderman
我添加了一个我想出来的 :) - Hemmelig
5个回答

3

这种方法基本上会在每次切片时更新字符串,因此我们可以直接使用a中的值作为索引值获得下一个值,而无需将它添加到现有的位置值中。

a = [1, 3, 4]
s = "01100110"
st = s
i = 0
while i < len(a):
    print(st[:a[i]])
    st = st[a[i]:]
    i+=1
 

输出结果

0
110
0110

这对于OP的请求有效,但我认为您应该考虑修改它以创建一个虚拟变量,而不是修改原始字符串,以防以后需要该变量。 - Steven Thomas
1
谢谢!我已经相应地编辑了答案。 - vnk
不错的改进。也许编写一个接受 sa 参数的函数是最佳方法。这取决于用户是否需要多次使用多个变量进行此操作,因为使用函数不应在内存中永久性地创建新变量。现在我们已经远远超出了最初的范围。 - Steven Thomas
1
这是一个很好的观点。但我们并不知道整个问题的背景,所以我想决定如何实现它应该由提问者自己来做。 - vnk

2
您可以将字符串转换为一个迭代器。然后,您可以根据给定的块大小简单地继续使用它:
it = iter(s)
["".join(next(it) for _ in range(chunk)) for chunk in a]
# ['0', '110', '0110']

您可以使用 itertools.islice 使其更加简洁:

from itertools import islice

it = iter(s)
["".join(islice(it, chunk)) for chunk in a]
['0', '110', '0110']

这非常优美(+1),但不幸的是非常低效。与 @balderman 的解决方案的 O(len(a)) 相比,这是 O(2 * i * len(a))。 - Michael Szczesny
不,它并不是。它和切片一样线性。此外,O(2* i * len(a)) == O(len(s))。而且两种方法的实际渐近复杂度都是O(len(s)) - user2390182
从技术上讲,是的。但是这个例子的运行时间要慢5倍,对于更大的切片来说甚至更慢。 - Michael Szczesny
@MichaelSzczesny 是的,这是可以预料到的。字符串切片是超级C优化的。但是迭代器模式对于这种情况很有用,因为您不需要跟踪序列中的位置。它可以使代码简洁易读。 - user2390182

2
以下是与“切片”相关的解决方案:

类似以下内容的东西是与之配套的“切片”解决方案

a = [1, 3, 4]
s = "01100110"
offset = 0
for x in a:
    print(f'{s[offset: offset+x]}')
    offset += x

输出

0
110
0110

1
我认为最简洁的解决方案是直接循环遍历a中的索引,如下所示:
a = [1, 3, 4]
s = "01100110"
bgn = 0
for i in a:
    end = bgn + i
    # The wanted slice
    print(s[bgn:end])  # 0, 110, 0110
    # The next slice begins where this one left off
    bgn = end

如果您需要结果,您可以将它们打包成一个列表:
a = [1, 3, 4]
s = "01100110"
results = []
bgn = 0
for i in a:
    end = bgn + i
    results.append(s[bgn:end])
    bgn = end
print(results)  # ['0', '110', '0110']

你可以使用列表推导式,但我认为这会降低可读性,因此不是正确的方法。

0

由于我最初的回答有误,现在进行修改。

I = 0 # inital starting index
i = 0 # counter for len(a)
while i < len(a):
    J = sum(a[:i+1]) # second starting index
    print(s[I:J]) # or whatever function you need
    I = J # making starting index for next loop equal to this starting index
    i += 1 # increment counter
0
110
0110

你说得对,我误读了原帖的输出。我应该删除还是修改我的回答? - Steven Thomas

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