如何根据某些条件在Ruby中扩展字符串?

时间:2016-10-07 07:32:44

标签: ruby-on-rails ruby string

我有一个字符串a5bc2cdf3。我想将其扩展为aaaaabcbccdfcdfcdf

在字符串中为a5,因此结果字符串应包含5个连续的“a”s,“bc2”导致“bc”连续出现2次,而cdf应重复{{1}时间。

如果输入为3,输出为a5bc2cdf3,我该如何在Ruby方法中执行此操作?

aaaaabcbccdfcdfcdf

4 个答案:

答案 0 :(得分:3)

您可以使用像

这样的正则表达式
.gsub(/([a-zA-Z]+)(\d+)/){$1*$2.to_i}

请参阅Ruby online demo

/([a-zA-Z]+)(\d+)/将匹配带有1个以上字母(([a-zA-Z]+))和1+个数字((\d+))的存根串,并将它们捕获为2个组,这些组稍后在块内使用以返回你需要的字符串。

请注意,您可以考虑使用可以匹配任何字母的[a-zA-Z]代替\p{L}

一旦在原始"压缩"中达到指定的索引,您想要突破gsub串。仍有可能,请参阅this Ruby demo

s = 'a5bc2cdf3'                # input string
index = 5                      # break index
result = ""                    # expanded string
s.gsub!(/([a-zA-Z]+)(\d+)/){   # regex replacement
    result << $1*$2.to_i       # add to the resulting string
    break if Regexp.last_match.end(0) >= index  # Break if the current match end index is bigger or equal to index
}
puts result[index]            # Show the result
# => b

为简洁起见,您可以将Regexp.last_match替换为$~

答案 1 :(得分:2)

我建议使用scan移动压缩字符串,使用一个简单的RegEx来检测非十进制字符组,然后将它们计为十进制/([^\d]+)(\d+)/

def get_character(compressed_string, index)
  result = nil

  compressed_string.scan(/([^\d]+)(\d+)/).inject(0) do |total_length, (chars, count)|
    decoded_string = chars * count.to_i
    total_length += decoded_string.length

    if index < total_length
      result = decoded_string[-(total_length - index)]
      break
    else
      total_length
    end
  end

  result
end

知道当前(总)长度,如果当前扩展字符串包括所请求的索引,则可以突破循环。该字符串永远不会完全解码。

此代码提供以下结果

get_character("a5bc2cdf3", 5)  # => "b"
get_character("a5bc2cdf3", 10) # => "d"
get_character("a5bc2cdf3", 20) # => nil

答案 2 :(得分:0)

另一种方式。我很喜欢Wiktor的方法。

def stringy str, index
  lets, nums = str.split(/\d+/), str.split(/[a-z]+/)[1..-1].map(&:to_i)
  ostr = lets.zip(nums).map { |l,n| l*n }.join
  ostr[index]
end

str = 'a5bc2cdf3'
p stringy str, 5 #=> "b"

答案 3 :(得分:0)

我使用:

str.split(/(\d+)/) # => ["a", "5", "bc", "2", "cdf", "3"]

以下是它如何分解:

split

这是有效的,因为/(\d+)/会返回正在分割的值,如果它在正则表达式组中:str.split(/(\d+)/).each_slice(2).to_a # => [["a", "5"], ["bc", "2"], ["cdf", "3"]]

each_slice(2)

可以使用str.split(/(\d+)/).each_slice(2).map { |s, c| s * c.to_i } # => ["aaaaa", "bcbc", "cdfcdfcdf"] 将生成的数组分解为要重复的字符串及其关联计数。

map

然后可以在使用String *的{​​{1}}中处理该数组数组,以重复这些字符。

最后join将所有生成的扩展字符串连接成一个字符串。