【问题标题】:String slicing by index list按索引列表对字符串进行切片
【发布时间】:2021-11-20 07:11:59
【问题描述】:

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

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)

【问题讨论】:

  • 你能分享你目前的代码吗?
  • 我添加了一个我想出的:)

标签: python python-3.x slice


【解决方案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']

您可以进行列表理解,但我认为这会降低可读性,以至于它不是正确的方法。

【讨论】:

    【解决方案2】:

    您可以将字符串转换为iterator。然后你可以简单地以给定的块大小继续使用它:

    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(2 * i * len(a)) 与 O(len(a)) 相比。
    • 不,不是。它和切片一样线性。另外,O(2* i * len(a)) == O(len(s))。两种方法的实际渐近复杂度是O(len(s))!
    • 嗯,技术上是的。但是这个例子的运行时间慢了 5 倍,对于更大的切片来说甚至更慢。
    • @MichaelSzczesny 是的,这是意料之中的。字符串切片是超级 C 优化的。但是对于不需要跟踪序列中位置的情况,了解迭代器模式是很好的选择。它使代码简洁易读。
    【解决方案3】:

    编辑,因为我最初的回答是错误的。

    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
    

    【讨论】:

    • 你说得对,我误读了 OP 的输出。我应该删除还是修改我的答案?
    【解决方案4】:

    这种方法基本上每次切片时都会更新字符串,因此我们只需将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
    

    【讨论】:

    • 这适用于 OPs 请求,但是我认为您应该考虑修改它以创建一个虚拟变量而不是修改原始字符串,以防以后需要该变量。
    • 谢谢!我已经相应地编辑了答案。
    • 很好的修正。也许采用sa 的函数将是最好的方法。这取决于人们是否需要对许多变量多次执行此操作,因为使用函数不应永久在内存中创建新变量。不过,我们现在已经超出了最初的范围。
    • 这很好。我们不知道这里问题的全部背景,所以我想由 OP 来决定如何实现它。
    【解决方案5】:

    类似下面的内容是“切片”解决方案

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

    输出

    0
    110
    0110
    

    【讨论】:

      猜你喜欢
      • 2014-07-08
      • 2016-08-29
      • 1970-01-01
      • 2018-06-11
      • 2015-10-01
      • 2012-07-13
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      相关资源
      最近更新 更多