代码之家  ›  专栏  ›  技术社区  ›  Madhan

用于比较具有相似键的哈希的代码段

  •  -1
  • Madhan  · 技术社区  · 13 年前

    我正在为rails编写集成测试,我想将创建的对象与发送的JSON对象进行比较。返回的对象与发送的对象不完全相同,(即)它有发送的对象没有的键,因为我正在使用活动模型序列化程序来提取返回对象中的关联。基本上,我只想比较两个对象之间所有相同的键,看看它是否相同。如果有一个干净高效的代码片段可以为我做到这一点,请告诉我!

    3 回复  |  直到 13 年前
        1
  •  2
  •   Todd A. Jacobs    13 年前

    TL;博士

    “聪明”的测试代码很少有用。每个测试都应该尽可能简单,并且应该测试某个对象的行为,而不是它的组成。不过,聪明总有办法的。

    使用阵列交点

    要做到这一点,一个难以理解的聪明方法是使用 Array#& 以找到关键点的交集,然后查找值之间的相等性。这将在一个相对平坦的散列上工作。例如:

    hash1 = {:key1=>"value1", :key2=>"value2", :key3=>"value3", :key4=>"value4"}
    hash2 = {:key1=>"value1", :key2=>"value2", :key5=>"value5"}
    Array(hash1.keys & hash2.keys).map { |k| hash1[k] == hash2[k] }.uniq
    #=> [true]
    

    如果您正在使用RSpec进行测试,您可以这样说:

    it 'has some matching key/value pairs' do
      # ... populate hash1
      # ... populate hash2
      Array(hash1.keys & hash2.keys).
        map { |k| hash1[k] == hash2[k] }.uniq.should == [true]
    end
    

    当然,如果期望值是错误的,那么您就不知道为什么,也不知道哪个键/值对是错误的。这只是您应该始终使用固定的输入和输出进行测试的众多原因之一,而不是尝试进行动态比较。

        2
  •  0
  •   the Tin Man    13 年前

    你可以使用 Hash#slice ,这是一个主动支持核心扩展。

    例如,如果要检查的密钥是 :a, :b, :c ,但结果包含 :a, :b, :c, :d , slice 将减少结果,只包含您关心的密钥:

    expected = { :a => 1, :b => 2, :c => 3 }
    result   = { :a => 1, :b => 2, :c => 3, :d => 4 }
    
    result.slice(:a, :b, :c) == expected
    # => true
    

    如果你得到了 NoMethodError: undefined method 'slice' 例外,您需要 active_support/core_ext/hash/slice

        3
  •  0
  •   the Tin Man    13 年前

    首先,找到两个哈希包含的键,然后比较这些键的值:

    hash1 = {:key1 => "value1", :key2 => "value2", :key3 => "value3", :key4 => "value4"}
    hash2 = {:key1 => "value1", :key2 => "value2", :key5 => "value5"}
    
    hash1_keys = hash1.keys
    hash2_keys = hash2.keys
    
    comparable_keys = hash1_keys.select{|key| hash2_keys.include?(key)}
    
    comparable_keys.each do |key|
      hash1[key].should == hash2[key]
    end