【问题标题】:Ruby - Sort array of arrays based on sum and object typeRuby - 根据总和和对象类型对数组进行排序
【发布时间】:2020-12-14 00:08:42
【问题描述】:

我有一个数组,具有不同的对象类型,如果非整数乘以 2 的总和大于或等于整个数组的总和,我希望从数组数组中提取数组。例如:

elements = [
  [1, 2, "3", "4"],
  [1, "2", "3", 5],
  ["1", 2, 3, "4.0"],
  [1, 2, 3, 4, "5"],
  [1, 2, 3.0, 4.0, 5.0]
]

expected output:

elements = [
  [1, 2, "3", "4"],
  ["1", 2, 3, "4.0"],
  [1, 2, 3.0, 4.0, 5.0]
]

由于字符串和浮点数之和大于或等于整数之和。

【问题讨论】:

    标签: arrays ruby object


    【解决方案1】:

    你可以使用:

    elements.select do |ary|
      ary.grep_v(Integer).sum(&:to_f) * 2 >= ary.sum(&:to_f)
    end
    #=> [[1, 2, "3", "4"], ["1", 2, 3, "4.0"], [1, 2, 3.0, 4.0, 5.0]]
    

    您也可以将to_f-call 传递给grep_v,即ary.grep_v(Integer, &:to_f).sum,但我更喜欢在双方都有相同的sum-calls。

    【讨论】:

    • 考虑到ary.grep_v(Integer).sum(&:to_f) = ary.sum(&:to_f) - ary.grep(Integer).sum,写2 * ary.grep(Integer).sum <= ary.sum(&:to_f) 可能更有效(部分取决于整数值的比例),尽管我不认为这很清楚(但是它确实避免了读者回答问题“grep_v 到底是什么?”)。
    【解决方案2】:

    创建一个 lambda 以乘以被调用的对象。我们需要将字符串转换为浮点数,因为字符串可以表示整数或浮点数。

    multiply = -> (x) {
      x = x.to_f if x.is_a? String
      x * 2 # both lines could of course be re-written at x.to_f * 2 as engineersmnky suggests, this was a verbose way of explaining the need to convert to float
    }
    

    反转 grep 整数对象,返回任何其他类型并将它们相乘以与映射到浮点数的数组进行交叉比较(以处理多种类型)。

    elements.select { |arr| arr.grep_v(Integer, &multiply).sum >= arr.map(&:to_f).reduce(:+) }
    

    【讨论】:

    • 我认为 lambda 可以合理地减少到 ->(x) {x.to_f * 2} 遵循 ruby​​ 的鸭子类型原则。现在如果说elements 包含[[["1",2]]] 那么grep_v 将收集子数组然后multiply 将导致[12,12] 但是通过添加to_f 消息将引发错误,这似乎更多符合过程的意图。或者更冗长的->(x) { x.to_r.to_f * 2} 来处理Strings,比如“1/2”
    • 更正我之前的评论multiply 将导致["1",2,"1",2]
    【解决方案3】:
    elements.select do |a|
      ints, non_ints = a.partition { |e| e.is_a? Integer }
      non_ints.sum(&:to_f) >= ints.sum
    end
      #=> [[1, 2, "3", "4"], ["1", 2, 3, "4.0"], [1, 2, 3.0, 4.0, 5.0]]
    

    Enumerable#partition。注意:

    a = elements[0]
      #=> [1, 2, "3", "4"] 
    ints, non_ints = a.partition { |e| e.is_a? Integer }
      #=> [[1, 2], ["3", "4"]] 
    
    a = elements[1]
      # => [1, "2", "3", 5] 
    ints, non_ints = a.partition { |e| e.is_a? Integer }
      #=> [[1, 5], ["2", "3"]]  
    

    等等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-01
      • 2017-09-29
      • 2013-12-01
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 2020-12-05
      相关资源
      最近更新 更多