【问题标题】:Ruby Acronym Creator from string来自字符串的 Ruby Acronym Creator
【发布时间】:2020-07-13 00:40:26
【问题描述】:

我正在创建一个函数,该函数接受一个字符串并创建一个首字母缩写词,但遇到了错误。 当我输入"Complementary metal-oxide semiconductor" 时,我在期待"CMOS" 时得到"CS" 作为回报。有什么建议为什么会发生这种情况?我传递了很多其他字符串,它可以工作,只是在这种情况下不起作用。

class Acronym

    def self.abbreviate(phrase)
        letters = phrase.split("")
        acronym = []
        letters.each do |letter|
            previous = letters.index(letter) - 1
            if previous == -1
                acronym.push(letter)
            elsif letters[previous] == " " || letters[previous] == "-"
                acronym.push(letter)
            end
        end
        acronym.join("").upcase
    end

end

【问题讨论】:

    标签: ruby loops acronym


    【解决方案1】:

    简化为

    def acronym(str)
      str.split(/ |-/).map(&:first).join.upcase
    end
    

    以上依赖于 Rails 的 activesupport 库。这是一个仅限 Ruby 的变体:

    str.split(/ |-/).map { |s| s[0] }.join.upcase 
    

    【讨论】:

    • 请注意,String::first() 是 ActiveSupport Core Extensions(也称为 Rails 的东西)的一部分。如果你在一个普通的 Ruby 应用程序中使用,你只需要安装 activesupport gem 并需要 ``activesupport/core_ext/string`。
    • @rmlockerd:此代码使用的是String#first,而不是String::first。否则,你的观点仍然成立。
    • 糟糕,是的,我的错。
    【解决方案2】:

    您的代码的问题是index() 返回给定字母的第一个 次出现。所以,有两个问题:

    1. “metal”中的“m”不是字符串中第一次出现的“m”。它出现在“互补”一词中。因此,每当它在字符串中看到“m”时,previous 将始终为“o”,因此不会触发push()
    2. 只要字符串中的第一个字母出现(无论位置如何),它都会触发您的第一个条件。如果您将测试字符串中的初始“C”更改为“c”,您可以看到效果。结果将是CSCC,因为“半导体”中有两个“c”。

    作为替代方案,这里有一个使用正则表达式的选项:

    def self.abbreviate(phrase)
      phrase.gsub('-', ' ')
            .scan(/(\A\w|(?<=\s)\w)/)
            .flatten
            .join.upcase
    end
    

    一步一步:

    1. 从@DollarChills 借用.gsub 将“-”变成空格。
    2. scan() 返回一个包含所有匹配项的数组。正则表达式匹配字符串中的第一个单词以及前面有空格的任何单词。
    3. scan 的结果实际上是一个数组数组,因此 flatten 将它们解除嵌套。
    4. 组合成一个字符串和大写

    【讨论】:

    • join('') == join
    • 漂亮,谢谢;从来没有注意到这一点。我将编辑答案以反映。
    【解决方案3】:

    您可以尝试使用gsub 忽略连字符。

    <%= ('Complementary metal-oxide semiconductor').gsub('-', ' ') %>
    

    回报:互补金属氧化物半导体

    【讨论】:

    • tr('-', ' ') 可以很好地替代 gsub 的使用。
    【解决方案4】:

    您在previous = letters.index(letter) - 1 中有一个错误

    看看你能不能发现它:

    arr = [:a, :b, :c, :a]
    previous_indexes = arr.map { |n| arr.index(n) - 1 }
    you_are_expecting = [-1, 0, 1, 2]
    
    previous_indexes == you_are_expecting
    # => false
    
    arr.index(:a) # => 0
    arr.index(:b) # => 1
    arr.index(:c) # => 2
    arr.index(:a) # => 0
    

    要通过迭代获取索引,请使用with_index

    arr = %i[a b c a]
    arr.map.with_index { |x, i| [x, i] }
    # => [[:a, 0], [:b, 1], [:c, 2], [:a, 3]]
    

    如果您进行了该修复,您的代码就会按照您的预期进行。

    不过有一个建议:您通常可以避免处理数组索引的细节。看看@Mori's answer 在更高层次上的运作方式。

    【讨论】:

      猜你喜欢
      • 2019-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 2023-03-25
      • 2011-09-11
      相关资源
      最近更新 更多