我想将字符串中的所有单词(字母)转换为像i18n那样的缩写。换句话说,我想将"extraordinary"
更改为" e11y"因为"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.") )
答案 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