代码之家  ›  专栏  ›  技术社区  ›  james

更正我的代码:按2个属性排序,如果第一个属性是两个值中的一个,则第一个属性服从第二个属性

  •  0
  • james  · 技术社区  · 7 年前

    鉴于:

    charges = [
      {payment_method:"card",amount:1000},
      {payment_method:"stripe",amount:500},
      {payment_method:"stripe",amount:1500},
      {payment_method:"card",amount:2000},
      {payment_method:"cash",amount:200},
      {payment_method:"cash",amount:4000},
    ]
    

    我想按照2条规则排序:

    我当前的代码是将卡片或条纹移到前面,但不按金额排序:

    charges.sort_by do |obj| 
      [ 
        (["card","stripe"].include? obj["payment_method"]) ? 0 : 1 , 
        obj["amount"]
      ]
    
    # result of MY sort:
    charges = [
      {:payment_method=>"card", :amount=>1000},
      {:payment_method=>"stripe", :amount=>500},
      {:payment_method=>"stripe", :amount=>1500},
      {:payment_method=>"card", :amount=>2000},
      {:payment_method=>"cash", :amount=>200},
      {:payment_method=>"cash", :amount=>4000},
    ]
    
    # result of DESIRED sort:
    charges = [
      {:payment_method=>"stripe", :amount=>500},
      {:payment_method=>"card", :amount=>1000},
      {:payment_method=>"stripe", :amount=>1500},
      {:payment_method=>"card", :amount=>2000},
      {:payment_method=>"cash", :amount=>200},
      {:payment_method=>"cash", :amount=>4000},
    ]
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Cary Swoveland    7 年前

    end 声明,我想它没有生存的剪切和粘贴)是散列没有键 "payment_method" 和 "amount" ( charges.first.keys #=> [:payment_method, :amount]

    通过更正,您的代码可以正常工作:

    charges.sort_by {|h| [["card", "stripe"].include?(h[:payment_method]) ? 0 : 1, h[:amount]]}
      # [{:payment_method=>"stripe", :amount=> 500},
      #  {:payment_method=>"card",   :amount=>1000},
      #  {:payment_method=>"stripe", :amount=>1500},
      #  {:payment_method=>"card",   :amount=>2000}, 
      #  {:payment_method=>"cash",   :amount=> 200},
      #  {:payment_method=>"cash",   :amount=>4000}]
    

    让我们更仔细地看看您的代码在做什么。

    因为散列没有键 "paymment_method" 和 “金额” , obj["paymment_method"] #=> nil obj["amount"] #=> nil 对所有人 obj . 因此,

    ["card","stripe"].include? obj["payment_method"]
    

    变成

    ["card","stripe"].include? nil
    

    哪个是 false 对所有人 目标 . 因此,排序数组的第一个元素 Enumerable#sort_by 总是 1 .

    sort_by Array#<=> 用于排序数组。 1 比较时 obj1["amount"] 和 obj2["amount"] ,实例方法 <=> 定义在 obj1 和 obj2

     obj1["amount"] <=> obj2["amount"] #=> nil <=> nil
    

    我们从

    nil.method(:<=>).owner #=> Kernel
    Array.ancestors        #=> [Array, Enumerable, Object, Kernel, BasicObject]
    

    NilClass 有一个实例方法 <=> 它是从 Kernel Object#<=> 2 )每当被比较的对象相等时返回零(这里是 nil <=> nil #=> 0 ). 因此,排序比较总是 [1, nil] <=> [1, nil]

    关于如何做到这一点的解释,见后一个文件——具体来说,第三段。

    Kernel#<=> Object 见链接处的第三段。

    推荐文章