Ruby 检查哈希值是否都为空或都有值

Ruby 检查哈希值是否都为空或都有值,ruby,hash,Ruby,Hash,我有两个长度相同的散列: hash1 = {"1"=>"val", "2"=>"val", "3"=>"", "4"=>""} hash2 = {"1"=>[""], "2"=>["value"], "3"=>["val1", "val2"], "4"=>[""]} 我需要比较一下。相应的键需要两者都有一个值(对于hash1,这意味着非空;对于hash2,这意味着数组中必须有一个非空值),或者两者都有一个空值(对于hash2,这意味着值为[“

我有两个长度相同的散列:

hash1 = {"1"=>"val", "2"=>"val", "3"=>"", "4"=>""} 
hash2 = {"1"=>[""], "2"=>["value"], "3"=>["val1", "val2"], "4"=>[""]} 
我需要比较一下。相应的键需要两者都有一个值(对于
hash1
,这意味着非空;对于
hash2
,这意味着数组中必须有一个非空值),或者两者都有一个空值(对于
hash2
,这意味着值为[“”])

  • “1”
    失败(数组有一个值,该值为空)
  • “2”
    通过(两者都有值)
  • “3”
    失败(
    hash1
    为空)
  • “4”
    通过(
    hash1
    为空,
    hash2
    在数组中有一个值,该值为空)

如果其中一个比较失败,那么我应该返回
false
。我不知道如何进行这样的比较。

假设哈希已经排序:

hash1 = {"1"=>"val", "2"=>"val", "3"=>"", "4"=>""} 
hash2 = {"1"=>[""], "2"=>["value"], "3"=>["val1", "val2"], "4"=>[""]} 

hash1.zip(hash2).all? do |(_, fv), (_, lv)| 
  fv.empty? ^ !lv.all?(&:empty?)
end
在这里,我们利用了使用
XOR
的优势。无论哈希是否排序,都需要进行预处理(排序)

根据@sawa和@CarySwoveland的评论,对于未排序的散列:

hash1.sort.zip(hash2.sort).all? do |(fk, fv), (lk, lv)| 
  #   ⇓ consistency        ⇓ true if one operand is truthy, other is falsey
  (fk == lk) && (fv.empty? ^ !lv.all?(&:empty?))
end

假设哈希已排序:

hash1 = {"1"=>"val", "2"=>"val", "3"=>"", "4"=>""} 
hash2 = {"1"=>[""], "2"=>["value"], "3"=>["val1", "val2"], "4"=>[""]} 

hash1.zip(hash2).all? do |(_, fv), (_, lv)| 
  fv.empty? ^ !lv.all?(&:empty?)
end
在这里,我们利用了使用
XOR
的优势。无论哈希是否排序,都需要进行预处理(排序)

根据@sawa和@CarySwoveland的评论,对于未排序的散列:

hash1.sort.zip(hash2.sort).all? do |(fk, fv), (lk, lv)| 
  #   ⇓ consistency        ⇓ true if one operand is truthy, other is falsey
  (fk == lk) && (fv.empty? ^ !lv.all?(&:empty?))
end
编辑:更好,我认为:

hash1.all? { |k,v| !(v.empty? ^ (hash2[k]==[""])) }
  #=> false
原始答复:

keys = hash1.keys
  #=> ["1", "2", "3", "4"] 
hash1.values_at(*keys).zip(hash2.values_at(*keys)).all? do |v1,v2|
  !(v1.empty? ^ (v2==[""]))
end
  #=> false
^
是Ruby的XOR运算符。

编辑:更好,我认为:

hash1.all? { |k,v| !(v.empty? ^ (hash2[k]==[""])) }
  #=> false
原始答复:

keys = hash1.keys
  #=> ["1", "2", "3", "4"] 
hash1.values_at(*keys).zip(hash2.values_at(*keys)).all? do |v1,v2|
  !(v1.empty? ^ (v2==[""]))
end
  #=> false
^
是Ruby的XOR运算符。

另一种方法:

def compare_hashes(hash1, hash2)
  (1..hash1.length).each do |n|
    n = n.to_s # can easily swap this if you want to use integers or symbols
    return false if hash1[n].empty? || hash2[n].empty? || hash2[n].all?(&:empty?)
  end

  true
end
另一种方法:

def compare_hashes(hash1, hash2)
  (1..hash1.length).each do |n|
    n = n.to_s # can easily swap this if you want to use integers or symbols
    return false if hash1[n].empty? || hash2[n].empty? || hash2[n].all?(&:empty?)
  end

  true
end

以下或多或少是需求的直接翻译。(*)


(*)OP规定两个散列具有相同数量的键,因此可能可以省略这种情况下的检查,但检查没有害处,并且所编写的方法在包含检查的情况下可能更有用(或至少更现实)。请随意省略。

以下或多或少是需求的直接翻译。(*)

hash1.merge(hash2){|_, v1, v2| v2.dup.push(v1)}
.all?{|_, v| v.all?(&:empty?) or v.none?(&:empty?)}
(*)OP规定两个散列具有相同数量的键,因此可能可以省略这种情况下的检查,但检查没有害处,并且所编写的方法在包含检查的情况下可能更有用(或至少更现实)。可以省略它

hash1.merge(hash2){|_, v1, v2| v2.dup.push(v1)}
.all?{|_, v| v.all?(&:empty?) or v.none?(&:empty?)}
或者按照@mudasobwa的建议:

hash2.merge(hash1){|_, v2, *v1| v1 + v2}
.all?{|_, v| v.all?(&:empty?) or v.none?(&:empty?)}
或者按照@mudasobwa的建议:

hash2.merge(hash1){|_, v2, *v1| v1 + v2}
.all?{|_, v| v.all?(&:empty?) or v.none?(&:empty?)}


不清楚您所说的“
hash2
有一个值且该值为空”是什么意思。也许您所说的“(需要其中之一)都有一个值(…)”是指其他内容。当这个条件满足时,另一个条件总是满足的。@sawa我更新了它。希望它能更清楚地解释为什么会通过。散列的整数键总是在1到散列长度的范围内吗?值是否总是hash1中的字符串和包含hash2中字符串的数组?如果
hash1={“1”=>“}
hash2={“1”=>[”,“]}
?不清楚您所说的“
hash2
有一个值而该值为空”是什么意思。也许您的意思是“(需要其中一个)都有一个值(…)”。当这个条件满足时,另一个条件总是满足的。@sawa我更新了它。希望它能更清楚地解释为什么会通过。散列的整数键总是在1到散列长度的范围内吗?值是否总是hash1中的字符串和包含hash2中字符串的数组?如果
hash1={“1”=>“}
hash2={“1”=>[“”,”“]}
?通过对块变量配置文件进行更详细的阐述,您可以摆脱
map
first
last
@sawa确实,谢谢。毕竟(请阅读:根据您的建议),这似乎是一个很好的解决方案。我们似乎一直在按照同样的思路思考。这取决于两个散列中的键顺序相同。@CarySwoveland这是OP的错。如果OP意味着订单没有保证,那么OP应该给出一个随机订单的例子。这是误导。同时,OP从未写过订单,因此您的解释也是合理的。@CarySwoveland。毕竟。我在回答中删除了一条关于排序的评论。通过对块变量配置文件进行更详细的阐述,您可以摆脱
映射
第一次
、和
最后一次
@sawa。确实,谢谢您。毕竟(请阅读:根据您的建议),这似乎是一个很好的解决方案。我们似乎一直在按照同样的思路思考。这取决于两个散列中的键顺序相同。@CarySwoveland这是OP的错。如果OP意味着订单没有保证,那么OP应该给出一个随机订单的例子。这是误导。同时,OP从未写过订单,因此您的解释也是合理的。@CarySwoveland。毕竟。我在回答中删除了一条关于排序的评论。Cary可能是假设哈希中的顺序不能保证。如果是,它可以变成
hash1.values.zip(hash2.values).
。我认为您的
v2.empty?
部分不正确。不止这些。不应该
v2.空吗?
应该
!v2.all(&:empty?
?@sawa,是的,我在中使用了
值,因为我没有假设键的顺序。@sawa,在
排序
中是的,但我假设
值在
中更快。Cary可能假设哈希中的顺序没有保证。如果是,它可以变成
hash1.values.zip(hash2.values).
。我认为您的
v2.empty?
部分不正确。不止这些。不应该
v2.空吗?
应该
!v2.all(&:empty?
?@sawa,是的,我在
中使用了
值,因为我没有假设键的顺序。@sawa,ye