我希望能够减去两个哈希并在Ruby中获得第三个哈希值。
这两个哈希看起来像这样:
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h1.default = 0
h2 = {"cat" => 50, "dog" => 3, "BIRD" => 4, "Mouse" => 75, "Snake" => 10}
h2.default = 0
我希望能够在h1上调用这样的方法:
h1.difference(h2)
并获得此哈希值:
{"Cat" => 50, "Dog" => 2, "BIRD" => -2, "Mouse" => -75}
我想创建一个新散列,其中包含来自两个散列的键和新散列的值,作为第一个散列中键的值减去第二个散列中该键的值。问题是,无论密钥的情况如何,我都希望这种Hash方法能够正常工作。换句话说,我希望“猫”与“猫”匹配。
这是我到目前为止所拥有的:
class Hash
def difference(another_hash)
(keys + another_hash.keys).map { |key| key.strip }.uniq.inject(Hash.new(0)) { |acc, key| acc[key] = (self[key] - another_hash[key]); acc }.delete_if { |key, value| value == 0 }
end
end
这没关系,但不幸的是,结果并不是我想要的。
任何帮助都将不胜感激。
答案 0 :(得分:4)
如何将哈希值转换为集合。
require 'set'
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h1.default = 0
h2 = {"cat" => 50, "dog" => 3, "BIRD" => 4, "Mouse" => 75, "Snake" => 10}
h2.default = 0
p (h1.to_set - h2.to_set)
#=> #<Set: {["Cat", 100], ["Dog", 5], ["Bird", 2]}>
答案 1 :(得分:3)
作为推荐......
我过去曾经使用过这样的东西:
class Hash
def downcase_keys
Hash[map{ |k,v| [k.downcase, v]}]
end
def difference(other)
Hash[self.to_a - other.to_a]
end
alias :- :difference
end
让我做的事情如下:
irb(main):206:0> h1.downcase_keys - h2.downcase_keys
{
"cat" => 100,
"dog" => 5,
"bird" => 2
}
irb(main):207:0> h2.downcase_keys - h1.downcase_keys
{
"cat" => 50,
"dog" => 3,
"bird" => 4,
"mouse" => 75
}
alias
为您提供了使用-
代替difference
的良好语法,类似于使用-
进行数组和集合。您仍然可以使用difference
:
irb(main):210:0> h1.downcase_keys.difference(h2.downcase_keys)
{
"cat" => 100,
"dog" => 5,
"bird" => 2
}
irb(main):211:0> h2.downcase_keys.difference(h1.downcase_keys)
{
"cat" => 50,
"dog" => 3,
"bird" => 4,
"mouse" => 75
}
我总是规范化我的哈希键,并且不允许变量泄漏。当你不知道键被调用时,它会使哈希处理太困难,所以我强烈建议你这样做。第一步。这是一个代码维护问题。
否则,您可以创建原始键名称及其规范化名称的映射,但如果您的哈希包含两个唯一大小写键,例如“key”和“KEY”,则会遇到问题,因为规范化将会踩踏之一。
答案 2 :(得分:0)
很抱歉,由于时间限制(我现在必须照顾我的男婴),只知道这个愚蠢但正常工作的代码:
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h1.default = 0
h2 = {"cat" => 50, "dog" => 3, "BIRD" => 4, "Mouse" => 75, "Snake" => 10}
h2.default = 0
h3 = {"Cat" => 50, "Dog" => 2, "BIRD" => -2, "Mouse" => -75}
class Hash
def difference(subtrahend)
diff = {}
self.each_pair do |k1, v1|
flag = false
subtrahend.each_pair do |k2, v2|
if k1.downcase == k2.downcase
flag = true
v_diff = v1 - v2
break if v_diff == 0
v_diff > 0 ? diff[k1] = v_diff : diff[k2] = v_diff
end
end
diff[k1] = v1 unless flag
end
subtrahend.each_pair do |k2, v2|
flag = false
self.each_pair do |k1, v1|
if k1.downcase == k2.downcase
flag = true
break
end
end
diff[k2] = -v2 unless flag
end
return diff
end
end
h1.difference(h2) == h3 ? puts("Pass") : puts("Fail") #=> "Pass"
答案 3 :(得分:0)
我得到了救援https://github.com/junegunn/insensitive_hash
然后按照您的程序进行调整,但需要稍加调整
require 'insensitive_hash'
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}.insensitive
h1.default = 0
h2 = {"cat" => 50, "dog" => 3, "BIRD" => 4, "Mouse" => 75, "Snake" => 10}.insensitive
h2.default = 0
class Hash
def difference(another_hash)
(keys + another_hash.keys).map { |key|
key.downcase }.uniq.inject(Hash.new(0)) do |acc, key|
val = self[key] - another_hash[key]
acc[key] = val if val!= 0
acc
end
end
end
h1.difference(h2)
# => {"cat"=>50, "dog"=>2, "bird"=>-2, "mouse"=>-75}