迭代哈希,并获取值,直到达到总和数限制

时间:2017-09-15 11:25:49

标签: arrays ruby hash

我有两个哈希数组,看起来像这样:

h1=[{id:1, item:1, value:10},
    {id:1, item:2, value:3}]

h2=[{id:1, item_a:1, value:5},{id:2, item_a:1, value:7},{id:3, item_a:1, value:10},
    {id:4, item_b:2, value:1},{id:5, item_b:2, value:2},{id:6, item_b:2, value:5},
    {id:7, item_b:2, value:1}]

我需要遍历h2和:

  1. 对于每个h1哈希,找到h2哈希,其item对应item_a,例如item值为1和{ {1}}值为item_a
  2. 从哈希1中取value,直到所有项目的总和等于或大于h2哈希h1中的项目,
  3. valueh1创建一个id数组数组,其第一个值为h2 id,第二个值为h1来自{{1} }}。
  4. 在上面的示例中,结果为id

    我在这里找到this answer,但它只是将值总结到某个定义的限制。我不知道如何获取值,直到达到总和的一部分。我希望有人可以指导我应该关注的方向。

    更新

    结果h2是因为:

    1. 来自[[1,1],[1,2],[1,4],[1,5]]我们会在[[1,1],[1,2],[1,4],[1,5]]h1处获取第一个哈希值,因此我们需要从item:1收集value:10的ID,因为我需要{{1} }}和h2值(在现实生活中 - ids),我们的总价值至少应为item_a:1
    2. 我们遍历1并从第一个哈希开始 - 其1小于10所以我们接受它,然后我们转到下一个哈希 - 它的h2和如果我们将其总结为之前的value:5,我们得到10 - 它大于value:7所以我们接受它并停止迭代,因为我们不允许再采取任何项目。我们的第一次迭代结果是:来自5哈希的{是12,来自10哈希的ID是h11。所以到目前为止我们的数组是h2
    3. 我们对来自1的第二个哈希做同样的事情,其中​​2的匹配 ID [[1,1],[1,2]]h1
    4. 更新2

      我正在清除我的例子,因为在两个哈希中只能有h2。 我想扩展我的例子。

      如果在45中添加额外条件item - from日期范围和to条件,代码会如何变更?

      date

      我想仅从那些h1 h2 h1=[{id:1, item:1, from: DateTime.new(2017,9,4,6,0,0,'+0300'), to: DateTime.new(2017,9,4,17,59,59,'+0300'), value:10}, {id:1, item:2, from: DateTime.new(2017,9,4,18,0,0,'+0300'), to: DateTime.new(2017,9,4,23,59,59,'+0300'), value:10}] h2=[{id:1, item:1, date: DateTime.new(2017,9,4,6,10,0,'+0300'), value:5}, {id:2, item:1, date: DateTime.new(2017,9,4,7,20,0,'+0300'), value:7}, {id:3, item:1, date: DateTime.new(2017,9,4,8,05,0,'+0300'), value:10}, {id:4, item:2, date: DateTime.new(2017,9,4,18,19,10,'+0300'), value:1}, {id:5, item:2, date: DateTime.new(2017,9,4,19,20,0,'+0300'), value:2}, {id:6, item:2, date: DateTime.new(2017,9,4,22,22,0,'+0300'), value:5}, {id:7, item:2, date: DateTime.new(2017,9,4,23,0,0,'+0300'), value:1}] date h2h1from范围内的哈希中获取ID。我想我应该把这个to放在某个地方。

2 个答案:

答案 0 :(得分:2)

首先我做了几个假设,你在描述中根本没有提到item_b,只说明h1和{{1}之间的链接}是关键h2,所以我假设item_aitem_a是等价的......也就是说,你不会有item_b之类的东西您不希望考虑item_b: 1中的第一个哈希值,因为它是h1而不是item_b。如果情况不正确,您需要相应调整以下代码(不应该太难)。

首先,如果您使用item_a键对h2中的项目进行分组会更容易,这样您就可以对它们进行简单的查找:

item_a/item_b

现在,h2 = h2.group_by { |item| item[:item_a] || item[:item_b] } # => {1=>[ {:id=>1, :item_a=>1, :value=>5}, {:id=>2, :item_a=>1, :value=>7}, {:id=>3, :item_a=>1, :value=>10} ], 2=>[ {:id=>4, :item_b=>2, :value=>1}, {:id=>5, :item_b=>2, :value=>2}, {:id=>6, :item_b=>2, :value=>5}, {:id=>7, :item_b=>2, :value=>1} ] } 包含映射到h2[1]第一行的所有项目(基于h1键)。接下来,您要将item中的值映射到数组列表,其中h1来自idh1来自id和{{1}来自h2的{​​s}来自id循环,跟踪总和:

h2

最后,您需要压平1级才能获得所需的结果:

take_while

答案 1 :(得分:1)

我对:item_a中的密钥:item_b:item_c(以及大概h2等)也有疑问。可以假设:item_a属于h1[0]:item_bh1[1],依此类推,但是更容易让它们具有相同的名称,我选择了是:item。也就是说,item_aitem_b不会使问题变得更加困难,它只会从编码的角度引入麻烦。

h1 = [{ id:1, item:1, value:10 }, { id:1, item:2, value:3 }]
h2 = [{ id:1, item:1, value:5 },  { id:2, item:1, value:7 }, { id:3, item:1, value:10 },
      { id:4, item:2, value:1 },  { id:5, item:2, value:2 }, { id:6, item:2, value:5},
      { id:7, item:2, value:1 }]

我假设,对于g中的每个哈希h1,如果g[:value]大于f[:value]的总和f { {1}} h2f[:item] = g[:item],对于所有此类哈希值[g[:id], f[:id],将包含在返回的数组中。 (哇!)相反,如果f应该被忽略,则g的值之和不足,只需要对下面的代码进行少量更改。

第一步是从h2构建另一个哈希。

h2

如您所见,h = h2.each_with_object({}) do |g, h| h.update(g[:item]=>[[g[:id], g[:value]]]) do |_, o, n| o << [g[:id], o.last.last + g[:value]] end end #=> {1=>[[1, 5], [2, 12], [3, 22]], 2=>[[4, 1], [5, 3], [6, 8], [7, 9]]} 的密钥等于h的值,以及:item值对和:id的“累积”值对的数组值。

:value

计算h1.each_with_object([]) do |g, a| id1 = g[:id] value1 = g[:value] arr = h[g[:item]] i = arr.index { |_id2, cum| value1 <= cum } || (arr.size - 1) arr[0..i].map(&:first).each { |id2| a << [id1, id2] } end #=> [[1, 1], [1, 2], [1, 4], [1, 5]] 后的步骤如下:

h

如果有a = [] g = { id:1, item:1, value:10 } id1 = g[:id] #=> 1 value1 = g[:value] #=> 10 arr = h[g[:item]] #=> h[1] #=> [[1, 5], [2, 12], [3, 22]] i = arr.index { |_id2, cum| value1 <= cum } || (arr.size - 1) #=> 1 ,说value1,我们会获得100。在这种情况下,arr.index { |_id2, cum| value1 <= cum } #=> nil设置为等于“或”字词i

arr.size - 1

其余的计算方法类似。