在Ruby中从末尾切片字符串
Posted
技术标签:
【中文标题】在Ruby中从末尾切片字符串【英文标题】:Slice string from end in Ruby 【发布时间】:2016-06-05 17:33:30 【问题描述】:如何将一个字符串拆分为多个长度相等但从后面开始的子字符串?
例如如果字符串是:"ABCDEFGH"
,那么我想要每个长度为 3 的字符串的数组为:
["FGH", "CDE", "AB"]
【问题讨论】:
【参考方案1】:您可以使用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".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")
【讨论】:
【参考方案3】:split
和 scan
也可以,但就像@meagar 指出的那样,您需要反转然后重新反转字符串:
"ABCDEFGH".reverse.split(/(...)/).reject(&:empty?).map(&:reverse)
# => ["FGH", "CDE", "AB"]
扫描不需要寻找空字符串:
"ABCDEFGH".reverse.scan(/...?/).map(&:reverse)
# => ["FGH", "CDE", "AB"]
【讨论】:
【参考方案4】:"ABCDEFGH".scan(/.+?(?=(?:.3)*\z)/) # => ["AB", "CDE", "FGH"]
"ABCDEFGH".scan(/.+?(?=(?:.3)*\z)/).reverse # => ["FGH", "CDE", "AB"]
【讨论】:
我不建议将它用于生产代码,它是一个强烈的正则表达式,但它确实很好用。【参考方案5】:您可以使用带有一些切片算法的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"]
【讨论】:
以上是关于在Ruby中从末尾切片字符串的主要内容,如果未能解决你的问题,请参考以下文章