【问题标题】:Ruby : How to sort an array of hash in a given order of a particular keyRuby:如何以特定键的给定顺序对哈希数组进行排序
【发布时间】:2014-02-10 09:18:07
【问题描述】:

我有一个哈希数组,id 是哈希中的键之一。我想根据ID 值的给定顺序对数组元素进行排序。

假设我的数组(size=5)是:

[{"id"=>1. ...}, {"id"=>4. ...}, {"id"=>9. ...}, {"id"=>2. ...}, {"id"=>7. ...}]

我想对数组元素进行排序,使其ids 的顺序如下:

[1,3,5,7,9,2,4,6,8,10]

所以预期的结果是:

[{'id' => 1},{'id' => 7},{'id' => 9},{'id' => 2},{'id' => 4}]

【问题讨论】:

    标签: ruby arrays sorting hash


    【解决方案1】:

    这是任何自定义索引的解决方案:

    def my_index x 
      # Custom code can be added here to handle items not in the index.
      # Currently an error will be raised if item is not part of the index.
      [1,3,5,7,9,2,4,6,8,10].index(x) 
    end
    
    my_collection = [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
    p my_collection.sort_by{|x| my_index x['id'] } #=> [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]
    

    然后你可以用任何你想要的方式格式化它,也许这样更漂亮:

    my_index = [1,3,5,7,9,2,4,6,8,10]
    my_collection.sort_by{|x| my_index.index x['id'] }
    

    【讨论】:

      【解决方案2】:

      我会根据以下值映射散列:

      a = [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
      
      [1,3,5,7,9,2,4,6,8,10].map{|x| a[a.index({"id" => x})] }.compact
      
      #=> [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]
      

      【讨论】:

        【解决方案3】:

        关于排序的一般说明。使用类的#sort_by方法:

        [{'id' => 1},{'id'=>3},{'id'=>2}].sort_by {|x|x['id'] }
        # => [{"id"=>1}, {"id"=>2}, {"id"=>3}]
        

        或者使用#values方法作为回调:

        [{'id' => 1},{'id'=>3},{'id'=>2}].sort_by(&:values)
        # => [{"id"=>1}, {"id"=>2}, {"id"=>3}]
        

        或者你可以用#sort方法使用更明显的版本:

        [{'id' => 1},{'id'=>3},{'id'=>2}].sort {|x,y| x['id'] <=> y['id'] }
        # => [{"id"=>1}, {"id"=>2}, {"id"=>3}]
        

        对于您的情况,要使用扩展条件进行排序,请使用 #% 拆分偶数和奇数索引:

        [{'id' => 1},{'id'=>4},{'id'=>9},{'id'=>2},{'id'=>7}].sort do |x,y|
            u = y['id'] % 2 <=> x['id'] % 2
            u == 0 && y['id'] <=> x['id'] || u 
        end
        # => [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]
        

        对于您的情况,要使用扩展条件进行排序,请使用#% 根据索引进行拆分,即使索引数组中不存在id 值:

        index = [1,3,5,7,4,2,6,8,10] # swapped 2 and 4, 9 is absent
        
        [{'id' => 1},{'id'=>4},{'id'=>9},{'id'=>2},{'id'=>7}].sort do |x,y|
           !index.rindex( x[ 'id' ] ) && 1 || index.rindex( x[ 'id' ] ) <=> index.rindex( y[ 'id' ] ) || -1 
        end
        # => [{"id"=>1}, {"id"=>7}, {"id"=>4}, {"id"=>2}, {"id"=>9}]
        

        【讨论】:

        • 预期结果是[{'id' =&gt; 1},{'id' =&gt; 7},{'id' =&gt; 9},{'id' =&gt; 2},{'id' =&gt; 4}]
        • @Малъ 我喜欢干净的解决方案。
        • @МалъСкрылевъ 这适用于这种特殊情况(奇数然后偶数),但有一个通用的解决方案。我可能会遇到理想的顺序是随机的情况
        • @МалъСкрылевъ :例如所需的顺序是 [1,5,3,2,8,9,7,6,4]
        • 所以,看看我已经回答过问题的答案。
        【解决方案4】:

        为什么不只是sort

        def doit(arr, order)
          arr.sort { |h1,h2| order.index(h1['id']) <=> order.index(h2['id']) }
        end
        
        order = [1,3,5,7,9,2,4,6,8,10]
        arr = [{'id' => 1}, {'id' => 4}, {'id' => 9}, {'id' => 2}, {'id' => 7}]     
        
        doit(arr, order)
          #=> [{'id' => 1}, {'id' => 7}, {'id' => 9}, {'id' => 2}, {'id' => 4}]     
        

        【讨论】:

          【解决方案5】:
          a= [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
          b=[1,3,5,7,9,2,4,6,8,10]
          a.sort_by{|x| b.index (x['id'])}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-05-30
            • 1970-01-01
            • 2015-02-07
            • 2014-12-08
            • 1970-01-01
            • 2018-05-23
            • 1970-01-01
            • 2014-03-05
            相关资源
            最近更新 更多