仅将修改应用于Ruby中的子字符串

时间:2016-01-27 14:08:46

标签: ruby-on-rails ruby

我有一个形式的字符串" award.x_initial_value.currency"而且除了领先的" x _"这样我得到了一个结果:" award.x_initialValue.currency"。 我目前的实施是:

a = "award.x_initial_value.currency".split(".")
b = a.map{|s| s.slice!("x_")}
a.map!{|s| s.camelize(:lower)}
a.zip(b).map!{|x, y| x.prepend(y.to_s)}

我对它不是很满意,因为它既不快也不优雅,性能是关键,因为它将应用于大量数据。 我也用谷歌搜索但却找不到任何东西 是否有更快/更好的方法来实现这一目标?

3 个答案:

答案 0 :(得分:5)

由于"性能是关键" ,您可以跳过ActiveSupport::Inflector的开销,并使用正则表达式来执行"驼峰"自己:

a = "award.x_initial_value.currency"
a.gsub(/(?<!\bx)_(\w)/) { $1.capitalize }
#=> "award.x_initialValue.currency"

答案 1 :(得分:2)

▶ "award.x_initial_value.x_currency".split('.').map do |s|
    "#{s[/\Ax_/]}#{s[/(\Ax_)?(.*)\z/, 2].camelize(:lower)}"
  end.join('.')
#⇒ "award.x_initialValue.x_currency"

或者,只需一次gsub次迭代:

▶ "award.x_initial_value.x_currency".gsub(/(?<=\.|\A)(x_)?(.*?)(?=\.|\z)/) do |m|
    "#{$~[1]}" << $~[2].camelize(:lower)
  end
#⇒ "award.x_initialValue.x_currency"

在后一版本中,我们使用全局替换:

  • $~是全局的简写,存储发生的最后一次正则表达匹配;
  • $~[1]是第一个匹配的实体,对应(x_)?,因为?它可能是匹配的字符串,或nil;这就是我们使用字符串外推的原因,如果nil "#{nil}"将导致空字符串;
  • 毕竟,我们将camelized第二场比赛追加到上面讨论的字符串中;
  • NB 最后一场比赛取代$~,可以使用Regexp::last_match

答案 2 :(得分:0)

你能尝试像这样的东西:

'award.x_initial_value.currency'.gsub(/(\.|\A)x_/,'\1#').camelize(:lower).gsub('#','x_')

# => award.x_initialValue.currency

注意:# char的可以使用任何未使用的char作为当前名称/字符空间。