【问题标题】:How can I arrange k elements by frequency in Decreasing Order in Ruby?如何在 Ruby 的递减顺序中按频率排列 k 个元素?
【发布时间】:2021-03-12 15:49:01
【问题描述】:

给定数组 (array) [1, 1, 2, 2, 2, 3] 这个方法应该返回 (new_array) [2, 2, 2, 1, 1, 3]

这是我到目前为止所尝试的

  1. 将数组转换为哈希
  2. 键是元素,值是计数

如何重新创建array 以匹配new_array

【问题讨论】:

    标签: arrays ruby


    【解决方案1】:

    这是一种方法:

    array = [1,1,2,2,2,3]
    
    array.tally # This is the bit you did already. Note that this uses the new ruby 2.7 method. You get: {1=>2, 2=>3, 3=>1}
      .sort_by {|k, v| -v} # Now we have: [[2, 3], [1, 2], [3, 1]]
      .flat_map { |element, count| Array.new(count, element) }
    
    # And that gives the final desired result of:
    [2, 2, 2, 1, 1, 3]
    

    或者其他变体,沿着相同的思路:

    array.tally # {1=>2, 2=>3, 3=>1}
      .invert # {2=>1, 3=>2, 1=>3}
      .sort # [[1, 3], [2, 1], [3, 2]]
      .reverse # [[3, 2], [2, 1], [1, 3]]
      .flat_map { |element, count| [element] * count }
    

    或者,这里有一些完全不同的东西:

    array.sort_by { |x| -array.count(x) }
    

    【讨论】:

      【解决方案2】:

      这是另一个:

      array = [1,1,2,2,2,3]
      p array.group_by(&:itself).values.sort_by(&:size).flatten
      

      【讨论】:

        【解决方案3】:
        def sort_chunks_by_length(arr)
          arr.slice_when(&:!=).sort_by { |a| -a.size }.flatten
        end
        
        sort_chunks_by_length [1,1,2,2,2,3]
          #=> [2, 2, 2, 1, 1, 3] 
        sort_chunks_by_length [1,1,2,2,2,1,3,3]
          #=> [2, 2, 2, 1, 1, 3, 3, 1] 
        

        我假设对于第二个示例,所需的返回值如下所示,而不是:

          #=> [2, 2, 2, 1, 1, 1, 3, 3] 
        

        该示例的步骤如下。

        arr = [1,1,2,2,2,1,3,3]
        
        enum = arr.slice_when(&:!=)
          #=> #<Enumerator: #<Enumerator::Generator:0x00007ffd1a9740b8>:each> 
        

        这是以下的简写:

        enum = arr.slice_when { |x,y| x!=y }
        

        我们可以通过将这个枚举器转换为数组来查看将要生成的元素:

        enum.to_a
          #=> [[1, 1], [2, 2, 2], [1], [3, 3]] 
        

        继续,

        a = enum.sort_by { |a| -a.size }
          #=> [[2, 2, 2], [1, 1], [3, 3], [1]] 
        a.flatten
          #=> [2, 2, 2, 1, 1, 3, 3, 1]
        

        操作线可以替换为以下任何一种。

          arr.chunk(&:itself).map(&:last).sort_by { |a| -a.size }.flatten
          arr.chunk_while(&:==).sort_by { |a| -a.size }.flatten
        

        请参阅Enumerable#slice_whenEnumerable#sort_byEnumerable#chunkEnumerable#chunk_while

        【讨论】:

        • 您的方法假定原始数组是预先分块的。如果不是,例如array=[1,2,1,2,2,3],那么您使用 slice_whenchunk_while 的逻辑将不起作用。
        • 我猜你可以通过在逻辑中添加一个额外的sort 来解释这一点!
        • @Tom,根据我的假设,您的示例所需的返回值应该是[2,2,1,2,1,3],而不是[2,2,2,1,1,3]。其他人则假设相反。任何一种假设都可能是正确的,因为在这一点上问题是沉默的。它反映了用一个例子来说明问题的不足之处,我们一直在 SO 上看到。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-08
        • 1970-01-01
        • 2022-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-06
        相关资源
        最近更新 更多