【问题标题】:python string slicing with alternating stridespython字符串切片与交替步幅
【发布时间】:2019-08-26 04:47:39
【问题描述】:

是否有一种优雅的方式来执行 Python 切片的不止一个步幅?

例如,给定一个输入字符串,创建一个包含以下位置的字符的字符串:1,4,6,9,11,14,16,19 等等

输入示例:

s = "abcdefhijklmnopqrstuvwxyz"

输出:

out = "behkmpruwz"

【问题讨论】:

  • 我不认为直接在标准库中进行多步切片是可能的。如果您对使用 slicing 没有严格要求,则可以使用 lambda in join 或 zip 等选项

标签: python string slice


【解决方案1】:

这是一个可能满足您要求的正则表达式解决方案:

s = "abcdefhijklmnopqrstuvwxyz"
output = re.sub(r'.(.)..(.)', '\\1\\2', s)
print(s)
print(output)

打印出来:

abcdefhijklmnopqrstuvwxyz
behkmpruwz

该模式一次匹配五个字符,捕获捕获组\1\2 中的第二个和第五个字符。然后,它只是将这五个字符替换为两个单独捕获的字符。

这恰好适用于您的输入字符串,因为它的长度正好是 5 的倍数。请注意,我的模式不会对超过 5 倍数长度的任何字符 1 到 4 进行任何替换。

【讨论】:

  • 你能解释一下这个 RE 吗?是否像每 2 和 5 个字符一样?
  • 谢谢,顺便说一句,我喜欢 RE :-)。不确定这是所有者正在寻找的答案:-
  • 这个图案有点像一张脸(.)..(.) ...也许是微笑,因为它获得了赞成票。
  • “因为它的长度正好是 5 的倍数。” - IMO 提示示例字符串中有错字(缺少 g),因为这不是字母表是真的...... :)
  • @SpghttCd 我的意思是,如果输入确实 not 必须是 5 的倍数,那么 OP 应该真正告诉我们在这种情况下会发生什么。一种可能的解释是,除非我们同时存在 1-1 和 2-1,否则不会发生切片。
【解决方案2】:

如果您不想使用外部库,那么一种通用的解决方案是自己计算正确的索引并加入相应的字符。

start1 = 0
start2 = 1
stride1 = 5
stride2 = 3

result = ''.join([s[i + j] for i in range(start1, len(s), stride1) 
                           for j in range(start2, stride1, stride2)])

如果您不介意使用 numpy 等库,那么您可以将输入设为 N 维数组(在本例中为二维矩阵)并在多个轴上应用高级切片。

import numpy as np

start1 = 0
start2 = 1
stride1 = 5
stride2 = 3
s_mat = np.array([*s]).reshape(stride1, -1)  # Reshape the input into a 5 by 5 matrix
result_mat = s_mat[start1:, start2::stride2].flatten()   # Apply slicing and flatten the result into a 1-D array
result = ''.join(result_mat)  # Merge the output array into a string

【讨论】:

    【解决方案3】:

    我试图像这样简化循环。不确定它是否完美契合。

    stride_1_seq = s[1::3]
    stride_2_seq = s[4::5]
    extracted_str = "".join(map(lambda x,y: x+y, stride_1_seq, stride_2_seq))
    

    如果间隔配置得当,这应该可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 2011-10-24
      • 2018-11-26
      • 2014-07-21
      • 2012-02-15
      • 1970-01-01
      相关资源
      最近更新 更多