【问题标题】:How to detect wether or not a string is a pangram and return true or false如何检测字符串是否为 pangram 并返回 true 或 false
【发布时间】:2021-01-21 16:34:02
【问题描述】:

pangram 是一个句子,它包含字母表中的每个字母至少一次。例如,句子“The quick brown fox jumps over the lazy dog”是一个 pangram,因为它至少使用了一次字母 A-Z(大小写无关)。我正在尝试创建一个方法,该方法接受一个字符串并返回真或假,如果它是一个 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

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

【问题讨论】:

  • 在您的第二个示例中,string.downcase 不会更改原始字符串。使用#downcase!

标签: ruby methods pangram


【解决方案1】:

你可以选择类似的东西:

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

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

当前解决方案存在的问题

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

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

第二个也有问题:

  1. 第一行没有任何作用。它对字符串进行小写并处理结果
  2. String#count 效率低下;
  3. '' 将通过此测试,因为每个字母出现 0 次。例如&lt;= 1 次。

【讨论】:

    【解决方案2】:
    def pangram?(string)
      (("a".."z").to_a - string.downcase.chars).empty?
    end
    

    【讨论】:

    • ...或a = ("a".."z").to_a; a &amp; string.downcase.chars == a(但更喜欢你所拥有的)。
    • @CarySwoveland a = [*('a'..'z')] and a.&amp;(string.downcase.chars).size == a.size
    • engineersmnky 这行得通。 Cary Swoveland 抱歉,这行得通,但我不明白为什么。
    • @ChiaraAni &amp;Array#intersection 它将返回原始数组和参数数组中存在的所有元素,例如["b","c"] &amp; ["c"] #=&gt; ["c"]。在 Cary 的示例中,交集必须与原始交集等价才能使案例成立。这是有效的,因为在交集期间保留了原始顺序
    • @ChiaraAni 因为它只是为了好玩。喜欢这个('a'..'z').then {|a| a.to_a - string.downcase.chars}.empty?
    【解决方案3】:
    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' 转换为集合而不是数组,只是为了加快计算速度。

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

    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
    

    【讨论】:

    • @engineersmnky,是的,我考虑过这一点,并进行了编辑,但在保存之前改变了主意。我会提到它。
    猜你喜欢
    • 2014-09-06
    • 1970-01-01
    • 2013-10-17
    • 2017-06-29
    • 1970-01-01
    • 2019-12-17
    • 2019-02-28
    • 2022-12-04
    • 2022-11-13
    相关资源
    最近更新 更多