1

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

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
4

4 回答 4

5

简化为

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

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

str.split(/ |-/).map { |s| s[0] }.join.upcase 
于 2020-07-13T00:46:42.357 回答
2

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

  1. 'metal' 中的 'm' 不是字符串中第一次出现的 'm'。它出现在“互补”一词中。因此,每当它在字符串中看到 'm' 时,previous 将始终为 'o',因此不会触发 a 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. 组合成一个字符串和大写
于 2020-07-13T02:36:08.493 回答
2

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

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

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

于 2020-07-13T00:48:16.390 回答
1

你有一个错误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 的答案是如何通过更高级别的操作来工作的。

于 2020-07-13T02:13:12.030 回答