7

配列を含む2つのハッシュがあります。私の場合、配列要素の順序は重要ではありません。RSpec2でそのようなハッシュを一致させる簡単な方法はありますか?

{ a: [1, 2] }.should == { a: [2, 1] } # how to make it pass?

PS

順序を無視する配列のマッチャーがあります。

[1, 2].should =~ [2, 1] # Is there a similar matcher for hashes?

解決

解決策は私のために働きます。もともとはトークランドによって提案されましたが、修正が加えられています。

RSpec::Matchers.define :match_hash do |expected|
  match do |actual|
    matches_hash?(expected, actual) 
  end
end

def matches_hash?(expected, actual) 
  matches_array?(expected.keys, actual.keys) &&
    actual.all? { |k, xs| matches_array?(expected[k], xs) }
end   

def matches_array?(expected, actual)
  return expected == actual unless expected.is_a?(Array) && actual.is_a?(Array)
  RSpec::Matchers::BuiltIn::MatchArray.new(expected).matches? actual
end

マッチャーを使用するには:

{a: [1, 2]}.should match_hash({a: [2, 1]})
4

4 に答える 4

2

カスタムマッチャーを作成します。

RSpec::Matchers.define :have_equal_sets_as_values do |expected|
  match do |actual|
    same_elements?(actual.keys, expected.keys) && 
      actual.all? { |k, xs| same_elements?(xs, expected[k]) }
  end

  def same_elements?(xs, ys)
    RSpec::Matchers::BuiltIn::MatchArray.new(xs).matches?(ys)
  end
end

describe "some test" do
  it { {a: [1, 2]}.should have_equal_sets_as_values({a: [2, 1]}) }  
end

# 1 example, 0 failures
于 2012-07-06T19:31:12.687 に答える
2

[Rspec 3]
次のように、ハッシュ値(配列)を並べ替えることになりました。

hash1.map! {|key, value| [key, value.sort]}.to_h
hash2.map! {|key, value| [key, value.sort]}.to_h
expect(hash1).to match a_hash_including(hash2)

しかし、かなり大きなアレイではうまく機能しないと確信しています...

于 2017-02-01T08:41:41.000 に答える
1

順序が重要でない場合は、配列の代わりにセットを使用できます。

require 'set'
Set.new([1,2]) == Set.new([2,1])
=> true
于 2012-07-06T19:33:13.760 に答える
1

==ハッシュは順序を気にしません、{1 => 2、3 => 4} == {3 => 4、1=>2}。ただし、値が等しいかどうかをチェックします。もちろん、[2,1]は[1,2]と等しくありません。〜=が再帰的であるとは思いません:[[1,2]、[3,4]]は[[4,3]、[2,1]]と一致しない可能性があります。含まれている場合は、キー用と値用の2つのチェックを記述できます。これは次のようになります。

hash1.keys.should =~ hash2.keys
hash1.values.should =~ hash2.values

しかし、私が言ったように、それはうまくいかないかもしれません。したがって、Hashクラスを拡張して、次のようなカスタムメソッドを含めることができます。

class Hash
  def match_with_array_values?(other)
    return false unless self.length == other.length
    return false unless self.keys - other.keys == []
    return false unless self.values.flatten-other.values.flatten == []
    return true
  end
end
于 2012-07-06T19:09:41.467 に答える