【问题标题】:How to count duplicates in Ruby Arrays如何计算 Ruby 数组中的重复项
【发布时间】:2010-12-18 10:23:05
【问题描述】:

如何计算 ruby​​ 数组中的重复项?

例如,如果我的数组有三个 a,我怎么能数到呢

【问题讨论】:

    标签: ruby arrays count duplicate-data


    【解决方案1】:

    Ruby >= 2.7 解决方案在这里:

    添加了一个新方法.tally

    统计集合,即计算每个元素的出现次数。返回一个以集合元素为键、对应计数为值的哈希。

    所以现在,你将能够做到:

    ["a", "b", "c", "b"].tally  #=> {"a"=>1, "b"=>2, "c"=>1}
    

    【讨论】:

      【解决方案2】:
      arr = [1, 2, "a", "a", 4, "a", 2, 1]
      
      arr.group_by(&:itself).transform_values(&:size)
      #=> {1=>2, 2=>2, "a"=>3, 4=>1}
      

      【讨论】:

        【解决方案3】:

        另一种方法是使用each_with_object

        a = [ 1, 2, 3, 3, 4, 3]
        
        hash = a.each_with_object({}) {|v, h|
          h[v] ||= 0
          h[v] += 1
        }
        
        # hash = { 3=>3, 2=>1, 1=>1, 4=>1 } 
        

        这样,调用不存在的键(例如 hash[5])将返回 nil 而不是 0Kim's solution

        【讨论】:

          【解决方案4】:

          获取数组中重复元素的Ruby代码:

          numbers = [1,2,3,1,2,0,8,9,0,1,2,3]
          similar =  numbers.each_with_object([]) do |n, dups|
              dups << n if seen.include?(n)
              seen << n 
          end
          print "similar --> ", similar
          

          【讨论】:

            【解决方案5】:

            我过去曾为此使用过reduce/inject,如下所示

            array = [1,5,4,3,1,5,6,8,8,8,9]
            array.reduce (Hash.new(0)) {|counts, el| counts[el]+=1; counts}
            

            生产

            => {1=>2, 5=>2, 4=>1, 3=>1, 6=>1, 8=>3, 9=>1}
            

            【讨论】:

              【解决方案6】:

              这将产生重复元素作为哈希值,其中包含每个重复项的出现次数。让代码说话:

              #!/usr/bin/env ruby
              
              class Array
                # monkey-patched version
                def dup_hash
                  inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { 
                    |k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r }
                end
              end
              
              # unmonkeey'd
              def dup_hash(ary)
                ary.inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { 
                  |_k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r }
              end
              
              p dup_hash([1, 2, "a", "a", 4, "a", 2, 1])
              # {"a"=>3, 1=>2, 2=>2}
              
              p [1, 2, "Thanks", "You're welcome", "Thanks", 
                "You're welcome", "Thanks", "You're welcome"].dup_hash
              # {"You're welcome"=>3, "Thanks"=>3}
              

              【讨论】:

              • 不再是-1,而是说真的……除非没有其他办法,否则不要打补丁。
              • 最后的.inject({}) { |r, e| r[e.first] = e.last; r } 有什么意义。 select 将返回一个哈希值,所以最终注入所做的只是,好吧,什么都没有。
              • 如果需要保留只出现一次的项目,可以将v &gt; 1改为v &gt; 0
              【解决方案7】:

              改进@Kim 的回答:

              arr = [1, 2, "a", "a", 4, "a", 2, 1]
              Hash.new(0).tap { |h| arr.each { |v| h[v] += 1 } }
              # => {1=>2, 2=>2, "a"=>3, 4=>1}
              

              【讨论】:

                【解决方案8】:

                我认为没有内置方法。如果您只需要 total 个重复项,则可以采用 a.length - a.uniq.length。如果您正在查找单个特定元素的计数,请尝试
                a.select {|e| e == my_element}.length

                【讨论】:

                  【解决方案9】:

                  另一种计算数组重复的方法是:

                  arr= [2,2,3,3,2,4,2]
                  
                  arr.group_by{|x| x}.map{|k,v| [k,v.count] }
                  

                  结果是

                  [[2, 4], [3, 2], [4, 1]]

                  【讨论】:

                    【解决方案10】:

                    很简单:

                    words = ["aa","bb","cc","bb","bb","cc"]
                    

                    一行简单的解决方案是:

                    words.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 }
                    

                    它对我有用。

                    谢谢!!

                    【讨论】:

                      【解决方案11】:
                      arr = %w( a b c d c b a )
                      # => ["a", "b", "c", "d", "c", "b", "a"]
                      
                      arr.count('a')
                      # => 2
                      

                      【讨论】:

                        【解决方案12】:

                        grep 呢?

                        arr = [1, 2, "Thanks", "You're welcome", "Thanks", "You're welcome", "Thanks", "You're welcome"]
                        
                        arr.grep('Thanks').size # => 3
                        

                        【讨论】:

                          【解决方案13】:

                          给定:

                          arr = [ 1, 2, 3, 2, 4, 5, 3]
                          

                          我最喜欢的元素计数方式是:

                          counts = arr.group_by{|i| i}.map{|k,v| [k, v.count] }
                          
                          # => [[1, 1], [2, 2], [3, 2], [4, 1], [5, 1]]
                          

                          如果您需要哈希而不是数组:

                          Hash[*counts.flatten]
                          
                          # => {1=>1, 2=>2, 3=>2, 4=>1, 5=>1}
                          

                          【讨论】:

                            【解决方案14】:

                            group_by 需要 1.8.7+

                            ary = %w{a b c d a e f g a h i b}
                            ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.map{|key,val| key}
                            # => ["a", "b"]
                            

                            对于 1.9+,这可以稍微简化,因为 Hash#select 将返回一个哈希。

                            ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.keys
                            # => ["a", "b"]
                            

                            【讨论】:

                              【解决方案15】:

                              要计算单个元素的实例,请使用注入

                              array.inject(0){|count,elem| elem == value ? count+1 : count}
                              

                              【讨论】:

                                【解决方案16】:

                                另一个版本的散列,其中每个元素都有一个键,每个元素的计数都有一个值

                                a = [ 1, 2, 3, 3, 4, 3]
                                h = Hash.new(0)
                                a.each { | v | h.store(v, h[v]+1) }
                                
                                # h = { 3=>3, 2=>1, 1=>1, 4=>1 } 
                                

                                【讨论】:

                                • 单行:[ 1, 2, 3, 3, 4, 3].reduce(Hash.new(0)) { |h, v| h.store(v, h[v] + 1); h }#reduce 通常比用于填充一个新变量的 #each 更受欢迎。
                                • 这是坚持 Ruby 方法订书钉的最干净的解决方案。我只想指出,这也适用于混合数组,并且在 Ruby 中,任何对象都可以是键!试着数数:[:a, :b, :a, 1, 10, 10, "b", "Bob", "Bob", "Bobby"]。它确实有效。
                                【解决方案17】:

                                简单。

                                arr = [2,3,4,3,2,67,2]
                                repeats = arr.length - arr.uniq.length
                                puts repeats
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2010-10-08
                                  • 1970-01-01
                                  • 2022-10-01
                                  • 2014-10-05
                                  • 1970-01-01
                                  • 2011-11-05
                                  • 2012-11-18
                                  • 2021-07-06
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多