【问题标题】:Hash subtraction in ruby红宝石中的哈希减法
【发布时间】:2017-07-13 18:27:05
【问题描述】:

我有 2 个哈希(稍后将转换为数组,不确定是否相关):

Hash1 = {"X"=>2, "Y"=>1, "Z"=>1}

Hash2 = {"X"=>1, "Y"=>1}

我需要像(Hash3 = Hash1 - Hash2)一样减去它们,并且我需要Hash3的结果,在这种情况下:

Hash3 = {"X"=>1, "Y"=>0, "Z"=>1}

我看到的所有示例和答案都导致结果哈希中不存在值等于 0 (Y) 的键,这不是我需要的。

我正在使用 Ruby 2.3.3 和 Rails 5.0

【问题讨论】:

  • 多说一些你的例子:不清楚。为什么选择 {"X" => 1} 而不是 {"X" => 2}? {"Y" => 0} 来自哪里?
  • 刚刚修改了语法
  • 哈希值表示数量,所以,我有第一个哈希是我的“库存”,第二个哈希是我的“当前使用”我需要得到的哈希是“可用的”。减法仅适用于值

标签: ruby-on-rails ruby


【解决方案1】:

你可以merge他们:

h1 = {"X"=>2, "Y"=>1, "Z"=>1}
h2 = {"X"=>1, "Y"=>1}

h1.merge(h2) { |k, v1, v2| v1 - v2 }
#=> {"X"=>1, "Y"=>0, "Z"=>1}

只要两个哈希中都存在一个键,就会调用该块来确定新值。


由于这种行为,如果密钥仅存在于 h2 中,它将不会导致负值:

h1 = {"X"=>2, "Y"=>1}
h2 = {"X"=>1, "Y"=>1, "Z"=>1}

h1.merge(h2) { |k, v1, v2| v1 - v2 }
#=> {"X"=>1, "Y"=>0, "Z"=>1}

你可能期望:

#=> {"X"=>1, "Y"=>0, "Z"=>-1}

tadman's solution 会返回什么。

【讨论】:

  • 这是merge 的一个非常好的功能。不知道它是这样做的。
  • +1,这个'减去两个哈希'的情况实际上是文档的用例:docs.ruby-lang.org/en/2.0.0/Hash.html#method-i-merge
  • @MickeySheu 哦,确实 :-)
  • 太棒了。这是最简单的方法,幸运的是我的模型不允许第二个哈希大于第一个。谢谢
  • 如果h1 = { "X"=>2, "Y"=>1, "Z"=>1 }, h2 = { "X"=>1, "Y"=>1, "W"=>2 } 并且期望的返回值是{ "X"=>1, "Y"=>0, "Z"=>1 },可以写成h1.merge(h2.select { |k,_| h1.key?(k) }) { |k, v1, v2| v1 - v2 } #=> {"X"=>2, "Y"=>0, "Z"=>1}。
【解决方案2】:

如果你把它分解成两个步骤并不太难:

def hash_sub(a, b)
  (a.keys + b.keys).uniq.map do |k|
    [ k, a[k].to_i - b[k].to_i ]
  end.to_h
end

hash_sub({"X"=>2, "Y"=>1, "Z"=>1}, {"X"=>1, "Y"=>1})
# => {"X"=>1, "Y"=>0, "Z"=>1}

第一步是通过组合两个散列中的键来计算所有可能的(唯一)键,然后通过从另一个中减去一个来转换为新的散列,强制转换为带有.to_i的整数。

【讨论】:

  • (a.keys + b.keys).uniq 可以短接为(a.keys | b.keys)
  • @Stefan 这是真的。我很想这样做,但它似乎更神秘。
  • @tadman 通常将| 视为“集合并集”(如“A|B := A 或 B 中存在的元素”)。知道了这一点,|'ing 密钥集就非常有意义。 :)
  • @tadman 我责怪 Rdoc。它将所有符号方法收集在顶部,但将| 放在底部。
【解决方案3】:

您也可以映射它们(但合并解决方案更好,因为它会负责从 2 中获取值,即使键不存在于 1 中):

hash3 = hash1.map{|k,v| { k: (v-(hash2[k.to_s] || 0)) }.stringify_keys }

这将产生一个数组

【讨论】:

    猜你喜欢
    • 2012-12-19
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    相关资源
    最近更新 更多