如何根据每个数组中不超过某个总和的值将哈希拆分为多个键组?

时间:2017-10-29 21:37:24

标签: arrays ruby hash

我有一个大哈希,其中键是名称,如“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的方式进行优化,但这是我猜的下一步......

提前非常感谢! 〜亚历

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

您可以像这样迭代哈希中的元素,解释在注释中:

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"]]

答案 2 :(得分:0)

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}]