【问题标题】:Ruby - Count the number of strings in an array that contain either of two charactersRuby - 计算数组中包含两个字符之一的字符串数
【发布时间】:2017-07-18 05:02:47
【问题描述】:

我有这个array

@a = ["P1 - D", "P3 - M", "P1 - D", "P1 - M", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - M", "P2 - D", "P2 - D", "P2 - D", "P2 - M", "P2 - M", "P3 - D", "P3 - D", "P - D", "P1 - M", "P - D", "P - D", "Post - D", "S1 - D", "P1 - M"]

每个string 都基于Page# - Device。所以P1 - D 是:Page1 - 桌面 & P3 - M 是:Page3 - 移动

如何找出array 中的string 中有多少个有DM

【问题讨论】:

  • 可能值得给出答案,你想要一个总数,即 27 或类似{"D"=>20, "M"=>7}
  • 您需要编辑标题以使其与问题一致。也许,“计算数组中包含两个字符之一的字符串的数量。”
  • 好的,谢谢@CarySwoveland

标签: arrays ruby include


【解决方案1】:

如果你只想要总数,你可以使用:

@a.grep(/D|M/).count
#=> 27

如果你想要小计,这应该是最有效的方法,因为它不会创建任何临时数组:

@a.each_with_object(Hash.new(0)) { |string, count| count[string[-1]] += 1 }
#=> {"D"=>20, "M"=>7}

【讨论】:

    【解决方案2】:
    a.group_by { |e| e[-1] }.each_with_object({}) { |(k, v), hash| hash[k] = v.count }
    #=> {"D"=>20, "M"=>7}
    

    步骤:

    groups = a.group_by { |e| e[-1] }
    # {
    #   "D"=> ["P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P2 - D", "P2 - D", "P2 - D", "P3 - D", "P3 - D", "P - D", "P - D", "P - D", "Post - D", "S1 - D"],
    #   "M"=> ["P3 - M", "P1 - M", "P1 - M", "P2 - M", "P2 - M", "P1 - M", "P1 - M"]
    # }
    
    group_counts = groups.each_with_object({}) { |(k, v), hash| hash[k] = v.count }
    #=> {"D"=>20, "M"=>7}
    
    group_counts['M']
    #=> 20
    

    编辑

    在 Ruby 2.4+ 中,您可以使用 Hash#transform_values(致谢 Alex Golubenko :)):

    a.group_by { |e| e[-1] }.transform_values(&:size)
    #=> {"D"=>20, "M"=>7}
    

    【讨论】:

    • 谢谢@Andrey,当我运行这个时,我得到了错误:undefined method last 请看看这个链接:function on repl.it
    • @user6589814 这很奇怪......你可以使用 group_by{ |el| el[-1] } 然后
    • a.group_by { |e| e[-1] }.transform_values(&:size) ;)
    • @AlexGolubenko transform_values!!不错,之前没用过
    • String#last 不是 Rails 方法吗?
    【解决方案3】:
    @a = ["P1 - D", "P3 - M", "P1 - D", "P1 - M", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - M", "P2 - D", "P2 - D", "P2 - D", "P2 - M", "P2 - M", "P3 - D", "P3 - D", "P - D", "P1 - M", "P - D", "P - D", "Post - D", "S1 - D", "P1 - M"]
    @a.count { |string| string.match(/D|M/) }
    #=> 27
    

    【讨论】:

    • 我最喜欢这个,因为它高效且读起来最好。预先设置count 可以告诉读者你在做什么。在 Ruby v2.4+ 中,您可以使用string.match? /D\M/,可以说它读起来更好。你当然可以使用/[DM]/ 而不是/D}M/。我建议你删除第一行。由于 OP 定义了@a,因此它是多余的,并且会使您的答案在视觉上不那么吸引人。
    【解决方案4】:
    @a.select { |word| word.include?('D') || word.include?('M') }.size
    # => 27
    

    【讨论】:

      【解决方案5】:

      可能的解决方案:

      @a.group_by { |e| e[-1] }.map {|e, a| [e, a.size]}.to_h
      => {"D"=>20, "M"=>7}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-17
        • 2015-05-24
        • 1970-01-01
        • 2011-06-01
        • 2018-06-06
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多