0

pangram 是一个包含字母表中的每个字母至少一次的句子。例如,句子“The quick brown fox jumps over the lazy dog”是一个 pangram,因为它至少使用了一次字母 AZ(大小写无关)。我正在尝试创建一个方法,该方法接受一个字符串并返回真或假,如果它是一个 pangram。这是我到目前为止所尝试的。

def pangram?(string)
  letters = string.chars.downcase.uniq
  letters.uniq.all? {|c| string.count(c)==26}
end

def pangram?(string)
  string.downcase
  ("a".."z").all?{|c| string.count(c) <= 1}
end

有更好的建议吗?提前致谢!

4

3 回答 3

4

你可以使用类似的东西:

s.downcase.scan(/[a-z]/).uniq.size == 26 

这会缩小字符串扫描从“a”到“z”的所有字符,并检查这些字符的 uniq 大小是否等于 26。

当前解决方案的问题

第一个永远不会按原样工作

  1. chars返回一个Array并且Array#downcase不是一个方法
  2. 您正在检查原始字符串中的每个字母是否出现 26 次 ( string.count(c)==26),因此'a' * 26将通过此测试,但“The quick brown fox jumps over the lazy dog”不会。

第二个也有问题:

  1. 第一行毫无用处。它对字符串进行小写并处理结果
  2. String#count将是低效的;
  3. ''将通过此测试,因为每个字母出现 0 次。例如<= 1时间。
于 2021-01-21T17:01:56.077 回答
1
def pangram?(string)
  (("a".."z").to_a - string.downcase.chars).empty?
end
于 2021-01-21T17:34:09.847 回答
1
require 'set'
def pangram?(str)
  str.downcase.each_char.with_object(('a'..'z').to_set) {|c,st| st.delete(c)}.empty?
end
pangram?("The quick brown dog jumps over the lazy fox")          #=> true
pangram?("The quick brown dog jumps over the lazy fo.")          #=> false
pangram?("The quick brown dog, Saffi, jumps over the lazy fox.") #=> true

我已经转换'a'..'z'为一个集合而不是一个数组,只是为了加快计算速度。

true如果字符串很长,一旦找到 26 个不同的字符就返回可能会更快:

def pangram?(str)
  str.downcase.each_char.with_object(('a'..'z').to_set) do |c,st|
    st.delete(c)
    return true if s.empty?
  end
  false
end
于 2021-01-21T19:01:14.180 回答