【问题标题】:Iteration in Ruby [duplicate]Ruby中的迭代[重复]
【发布时间】:2012-10-31 00:55:45
【问题描述】:

可能重复:
count duplicate elements in ruby array

我刚开始学习 ruby​​,我希望实现这样的目标。 假设我有一个数组

["student", "student", "teacher", "teacher", "teacher"]

我要做的是统计学生和老师的数量并将其存储到哈希中,这样我就可以得到

{:student= > 2, :teacher=> 3}

有人能给我一些关于如何做到这一点的方向吗?

【问题讨论】:

    标签: ruby arrays hash iteration


    【解决方案1】:

    你应该检查this的答案,它给出了这个例子:

    # sample array
    a=["aa","bb","cc","bb","bb","cc"]
    
    # make the hash default to 0 so that += will work correctly
    b = Hash.new(0)
    
    # iterate over the array, counting duplicate entries
    a.each do |v|
      b[v] += 1
    end
    
    b.each do |k, v|
      puts "#{k} appears #{v} times"
    end
    

    【讨论】:

      【解决方案2】:
      list = ["student", "student", "teacher"]
      
      # Initializing the hash with value 0 so that we can use += 1
      count = Hash.new(0)  
      
      list.each {|el| count[el] += 1}
      
      #Number of student  
      count['student']
      

      【讨论】:

        【解决方案3】:
        xs.inject({}) { |acc, x| acc.update(x => (acc[x] || 0) + 1) }
        #=> {"student"=>2, "teacher"=>3} 
        

        或者:

        xs.each_with_object(Hash.new(0)) { |x, acc| acc[x] += 1 }
        #=> {"student"=>2, "teacher"=>3}
        

        【讨论】:

        • fetch 会比update 更快吗?
        • @sawa。但是fetch 不是get 操作吗?不过既然提到了,值也可以写成(acc.fetch(x, 0) + 1)?
        【解决方案4】:

        这个特殊问题是如何选择正确算法的一个很好的例子,但更重要的是,正确的数据结构可以大大简化解决方案。事实上,在这种特殊情况下,选择正确的数据结构将使算法变得如此微不足道,以至于它基本上完全消失了:数据结构已经是答案。

        我正在谈论的数据结构是MultisetMultiset 就像Set,除了它不只存储唯一项目,而是存储每个项目在Multiset。基本上,Set 告诉您某个特定项目是否在 Set根本,此外,Multiset 还告诉您该特定项目的频率多久Multiset.

        很遗憾,Ruby 核心库或标准库中没有 Multiset 实现,但网络上流传着一些实现。

        您实际上只需要从您的Array 构造一个Multiset。这是一个例子:

        require 'multiset'
        
        ary = ["student", "student", "teacher", "teacher", "teacher"]
        
        print Multiset[*ary]
        

        是的,仅此而已。这打印:

        #2 "student"
        #3 "teacher"
        

        就是这样。例如,使用https://GitHub.Com/Josh/Multimap/

        require 'multiset'
        
        histogram = Multiset.new(*ary)
        # => #<Multiset: {"student", "student", "teacher", "teacher", "teacher"}>
        
        histogram.multiplicity('teacher')
        # => 3
        

        例如,使用http://maraigue.hhiro.net/multiset/index-en.php

        require 'multiset'
        
        histogram = Multiset[*ary]
        # => #<Multiset:#2 'student', #3 'teacher'>
        

        另一种可能性是使用Hash,这基本上只是意味着您必须自己做而不是Multiset 为您处理元素计数:

        histogram = ary.inject(Hash.new(0)) {|hsh, item| hsh.tap { hsh[item] += 1 }}
        print histogram
        # { "student" => 2, "teacher" => 3 }
        

        但是,如果您不计算自己,而是使用Enumerable#group_by 将元素自己分组,然后将分组映射到它们的大小,那么您可以更轻松。最后,转换回Hash

        Identity = ->x { x }
        
        print Hash[[ary.group_by(&Identity).map {|n, ns| [n, ns.size] }]
        # { "student" => 2, "teacher" => 3 }
        

        【讨论】:

        • 您的最后两个解决方案已经在不同的答案中给出。
        • stackoverflow.com/a/4300282/38765 再次提及 Multisets,以及其他提及 Multisets 的链接。
        【解决方案5】:

        在 SO 上确实已经死了,但我建议:

        Hash[*a.group_by{|x| x}.flat_map{|k, v| [k.to_sym,v.size]}]
        #=> {:student=>2, :teacher=>3}
        

        【讨论】:

        • Hash[] 从 Ruby 1.8.7 开始接受对,不需要 * + 展平。
        【解决方案6】:
        a = ["student", "student", "teacher", "teacher", "teacher"]
        
        a.inject({}){|h, e| h[e] ||= a.count(e); h}
        # => {"student"=>2, "teacher"=>3}
        

        【讨论】:

        • 正如@RailsN00ob 的回答所发生的那样,这是 O(n^2)
        • @tokland 我认为它小于 O(n^2)。因为||=,它跳过了不必要的迭代。当它跳过时,它只是一个哈希查找:h[e],应该很快。我最初有一个与 RailsN00b 相同的答案,并意识到您提到的内容,并更改为我现在的答案。我的回答比这更有效。
        • 是的,由于计数的记忆,它可能会表现得更好,O(n*k) 其中 k 是 a 中的唯一元素。所以最好的情况是 O(n),最坏的情况仍然是 O(n^2)。但在一个明确的 O(n) 问题中......
        【解决方案7】:
        list = ["student", "student", "teacher", "teacher", "teacher"] #original list
        
        counts = {} #where the count hash will be
        
        list.uniq.map{|x| counts[x]= list.count(x)} 
        

        对于列表中的每个唯一项目,将其从原始列表中的计数放入计数哈希中。

        一行。干净简单。

        【讨论】:

        • 映射 O(n) 与计数 O(n) -> O(n^2)。糟糕的表现。
        • 查看问题。他刚开始学习红宝石。性能不是问题。
        猜你喜欢
        • 1970-01-01
        • 2023-03-23
        • 2016-10-24
        • 2018-08-29
        • 1970-01-01
        • 2012-03-23
        • 2016-07-15
        • 2017-08-23
        • 2017-02-10
        相关资源
        最近更新 更多