在Ruby中从字符串末尾切片

3
如何将一个字符串从后往前分成多个等长的子字符串?
例如,如果字符串是:"ABCDEFGH",那么我想要一个长度为3的字符串数组,如下所示:
["FGH", "CDE", "AB"]
5个回答

3
我认为这个可以满足你的需求:

我认为这个可以满足你的需求:

> "ABCDEFGH".reverse.scan(/.{1,3}/).each { |x| x.reverse! }
=> ["FGH", "CDE", "AB"]

这里是一个简单的解释: .reverse 将字符串反转,使其变为 "HGFEDCBA" 而不是 "ABCDEFGH".scan(/.{1,3}/)将字符串转换为一个数组,每个元素包含3个字符(如果字符串不能被3整除,则数组的最后一个元素可能有1或2个字符)。 .each { |x| x.reverse! } 反转数组中每个元素中的字符。
你可以像这样定义一个函数:
def slice_string_from_end(s)
  s.reverse.scan(/.{1,3}/).each { |x| x.reverse! }
end

然后你可以使用:

slice_string_from_end("ABCDEFGH")

2
您可以使用each_slice来实现这一点,但是您需要先反转字符串,然后再重新反转每个单独的片段:
x = "ABCDEFGH"
x.chars.reverse.each_slice(3).map(&:reverse).map(&:join)
=> ["FGH", "CDE", "AB"]
  • 将字符串拆分为字符数组 (x.chars)
  • 反转数组 (.reverse)
  • 将数组切片成每个子数组包含3个字符 (.each_slice(3))
  • 反转每个子数组 (.map(&:reverse))
  • 将每个子数组拼接回字符串 (.map(&:join))

2
"ABCDEFGH".scan(/.+?(?=(?:.{3})*\z)/) # => ["AB", "CDE", "FGH"]
"ABCDEFGH".scan(/.+?(?=(?:.{3})*\z)/).reverse # => ["FGH", "CDE", "AB"]

我不建议在生产代码中使用这个,因为它是一个非常复杂的正则表达式,但它确实运行良好。 - tadman

0

splitscan也可以使用,但正如@meagar所指出的那样,您需要先反转字符串,然后再次反转:

"ABCDEFGH".reverse.split(/(...)/).reject(&:empty?).map(&:reverse)
# => ["FGH", "CDE", "AB"]

扫描器不需要查找空字符串:

"ABCDEFGH".reverse.scan(/...?/).map(&:reverse)
# => ["FGH", "CDE", "AB"]

0
您可以使用带有一些切片算术的while循环:
s="ABCDEFGH"
li=[]
step=3
while s.length>0
    ss=s[-(step<s.length ? step : s.length)..-1]
    li << ss
    s.chomp!(ss)
end 

同样的方法适用于动态正则表达式:

s="ABCDEFGH"
li=[]
step=3
reg=".{1,#{step}}$"
while s.length>0
    ss=s[/#{reg}/]
    li << ss
    s.delete_suffix!(ss)
end 

无论哪种情况:

> li
=> ["FGH", "CDE", "AB"]

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