pierallard
pierallard

Reputation: 3371

Check if an array has same elements than other, regardless of the order

I'm not sure if its a Rspec question, but I only encountred this problem on Rspec tests.

I want to check if an array is equal to another array, regardless of the elements order :

[:b, :a, :c] =?= [:a, :b, :c]

My current version :

my_array.length.should == 3
my_array.should include(:a)
my_array.should include(:b)
my_array.should include(:c)

Is there any method on Rspec, ruby or Rails for do something like this :

my_array.should have_same_elements_than([:a, :b, :c])

Upvotes: 10

Views: 13612

Answers (5)

Swaps
Swaps

Reputation: 1548

I think all answers seems to be pretty old. Latest matcher is contain_exactly.

You can simply do -

expect([:b, :a, :c]).to contain_exactly(:a, :b, :c)

Please not that in contain_exactly we don't pass a whole array, instead pass separate elements.

Ref - Rspec Guide

Upvotes: 3

Stefan
Stefan

Reputation: 114138

You can use the =~ operator:

[:b, :a, :c].should =~ [:a, :b, :c] # pass

From the docs:

Passes if actual contains all of the expected regardless of order. This works for collections. Pass in multiple args and it will only pass if all args are found in collection.

For RSpec's expect syntax there's match_array:

expect([:b, :a, :c]).to match_array([:a, :b, :c]) # pass

or contain_exactly if you're passing single elements:

expect([:b, :a, :c]).to contain_exactly(:a, :b, :c) # pass

Upvotes: 12

apneadiving
apneadiving

Reputation: 115511

Here was my wrong matcher (thanks @steenslag):

RSpec::Matchers.define :be_same_array_as do |expected_array|
  match do |actual_array|
    (actual_array | expected_array) - (actual_array & expected_array) == []
  end
end

Other solutions:

  • use the builtin matcher, best solution

  • use Set:

Something like:

require 'set'
RSpec::Matchers.define :be_same_array_as do |expected_array|
  match do |actual_array|
    Set.new(actual_array) == Set.new(expected_array)
  end
end

Upvotes: 2

Andy Waite
Andy Waite

Reputation: 11076

There is a match_array matcher in RSpec which does this:

http://rubydoc.info/github/rspec/rspec-expectations/RSpec/Matchers:match_array

Upvotes: 37

user946611
user946611

Reputation:

This should work.

[:b, :a, :c].sort == [:a, :b, :c].sort

Upvotes: 3

Related Questions