【问题标题】:How to split a hash into multiple arrays of keys based the values not exceeding a certain sum in each array?如何根据每个数组中不超过某个总和的值将哈希拆分为多个键数组?
【发布时间】:2017-10-29 21:37:24
【问题描述】:

我有一个大散列,其中键是名称,例如“Alex”,值是数字,例如“100”。 如何将此哈希拆分为包含键的多个数组,其中值的总和不超过某个阈值?

示例

我有哈希

{"Alex"=>50, "Bamby"=>100, "Jordan"=>300, "Ger"=>700, "Aus"=>500, "Can"=>360}

我想从一开始就将它分成 1000 包(不必从头开始,但会很好), 意思:

array1 = ["Alex", "Bamby", "Jordan"] # not "Ger" bc it would exceed the 1000 in sum

array2 = ["Ger"] # not the Aus because it again would exceed the 1000

array3 = ["Aus", "Can"]

最好的解决方案实际上是对其进行优化,使代码使数组全部接近或等于 1000,但我猜这是下一步...

提前非常感谢您! ~亚历克斯

【问题讨论】:

标签: arrays ruby hash


【解决方案1】:
h = {"Alex"=>50, "Bamby"=>100, "Jordan"=>300, "Ger"=>700, "Aus"=>500, "Can"=>360}

tot = 0
h.keys.slice_before { |k| (tot += h[k]) > 1000 ? tot = h[k] : false }.to_a
  #=> [["Alex", "Bamby", "Jordan"], ["Ger"], ["Aus", "Can"]]

如果tot > 1000 块返回一个真值(h[k])并且tot += h[k] 周围的括号是必要的。

Enumerable#slice_before

【讨论】:

    【解决方案2】:
    original = {"Alex"=>50, "Bamby"=>100, "Jordan"=>300, "Ger"=>700, "Aus"=>500, "Can"=>360}
    
    chunked = original.inject([]) do |array, (key, value)|
      array << {} unless array.any?
    
      if array.last.values.sum + value <= 1_000
        array.last.merge!(key => value)
      else
        array << { key => value }
      end
    
      array
    end
    
    # => [{"Alex"=>50, "Bamby"=>100, "Jordan"=>300}, {"Ger"=>700}, {"Aus"=>500, "Can"=>360}]
    

    【讨论】:

    • 使用Enumerable#chunk_while怎么样?我这么说是因为我注意到你的变量chunked
    • 因为我觉得在这种情况下哈希值是更符合人体工程学的输出。
    【解决方案3】:

    您可以像这样遍历散列中的元素,解释在 cmets 中:

    hash={"Alex"=>50, "Bamby"=>100, "Jordan"=>300, "Ger"=>700, "Aus"=>500, "Can"=>360}
    rs = [] # the outside array
    rss = [] # the array inside the array
    m = 0 # check if the sum of nexts are 1000
    hash.each do |key, n|
      if m+n <= 1000  # if the counter + the next element < 1000
        m += n # then add it to the counter
        rss << key # add the key to the actual array
      else
        rs << rss #else m is equal or bigger than 1000, so, I add all the keys to the main array
        m=n # the element that overcomes m to 1000, becomes the first count now
        rss=[key] # And that key is the first element of a new array
      end
    end
    rs << rss #Importan! at the end, the final array need to be added outside the loop
    
    print rs
    

    结果_

    => [["Alex", "Bamby", "Jordan"], ["Ger"], ["Aus", "Can"]]
    

    【讨论】:

    • 您似乎在使用 cmets 来完整地解释您的代码。最好在代码之前或之后写一个解释,在适当的地方加上几个 cmets。
    • @sagarpandya82 感谢您的评论,下次我会这样做,我发现它很清楚,所以您可以准确地看到我在说的那一行,但是是的,您是对的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 2016-11-04
    • 1970-01-01
    • 2018-06-17
    相关资源
    最近更新 更多