坚持使用ruby字符串的缩写实现

时间:2016-11-22 18:10:17

标签: ruby string

我想将字符串中的所有单词(字母)转换为像i18n那样的缩写。换句话说,我想将"extraordinary"更改为&#34; e11y&#34;因为"extraordinary"中的第一个和最后一个字母之间有11个字符。它适用于字符串中的单个单词。但是我如何才能为多字符串做同样的事情呢?当然,如果一个单词是<= 4,那么就没有必要从中做出缩写。

class Abbreviator

  def self.abbreviate(x)
    x.gsub(/\w+/, "#{x[0]}#{(x.length-2)}#{x[-1]}")
  end

end

Test.assert_equals( Abbreviator.abbreviate("banana"), "b4a", Abbreviator.abbreviate("banana") )
Test.assert_equals( Abbreviator.abbreviate("double-barrel"), "d4e-b4l", Abbreviator.abbreviate("double-barrel") )
Test.assert_equals( Abbreviator.abbreviate("You, and I, should speak."), "You, and I, s4d s3k.", Abbreviator.abbreviate("You, and I, should speak.") )

4 个答案:

答案 0 :(得分:5)

你的错误是你的第二个参数是一个替换字符串,作为一个整体在x(原始整个字符串)上运行。

不使用gsub形式的第二个参数是替换字符串,而是使用gsub的形式,其中第二个参数是(列出,用于例如,this page上的第三个)。现在,您正在接收块中的每个子字符串,并且可以单独对 子字符串进行操作。

答案 1 :(得分:1)

我会按照以下方式推荐一些内容:

class Abbreviator
  def self.abbreviate(x)
    x.gsub(/\w+/) do |word|
      # Skip the word unless it's long enough
      next word unless word.length > 4
      # Do the same I18n conversion you do before
      "#{word[0]}#{(word.length-2)}#{word[-1]}"
    end
  end
end

答案 2 :(得分:1)

def short_form(str)
  str.gsub(/[[:alpha:]]{4,}/) { |s| "%s%d%s" % [s[0], s.size-2, s[-1]] }
end

正则表达式读取“匹配四个或更多字母字符”。

short_form "abc"          # => "abc" 
short_form "a-b-c"        #=> "a-b-c" 
short_form "cats"         #=> "c2s" 
short_form "two-ponies-c" #=> "two-p4s-c" 
short_form "Humpty-Dumpty, who sat on a wall, fell over"
  #=> "H4y-D4y, who sat on a w2l, f2l o2r"

答案 3 :(得分:1)

接受的答案并不错,但是通过不匹配首先太短的单词可以使它变得更简单:

def abbreviate(str)
  str.gsub(/([[:alpha:]])([[:alpha:]]{3,})([[:alpha:]])/i) { "#{$1}#{$2.size}#{$3}" }
end

abbreviate("You, and I, should speak.")
# => "You, and I, s4d s3k."

或者,我们可以使用lookbehind和lookahead,这使得Regexp更复杂但替换更简单:

def abbreviate(str)
  str.gsub(/(?<=[[:alpha:]])[[:alpha:]]{3,}(?=[[:alpha:]])/i, &:size)
end