Rspec: "Array.Should == Another_Array" But Without Concern for Order

Rspec: array.should == another_array but without concern for order

Use match_array, which takes another array as an argument, or contain_exactly, which takes each element as a separate argument, and is sometimes useful for readability. (docs)

Examples:

expect([1, 2, 3]).to match_array [3, 2, 1]

or

expect([1, 2, 3]).to contain_exactly 3, 2, 1

Rspec - Check if an array have same elements than other, regardless of the order

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

RSpec expect to receive method with array but order does not matter

You can pass any RSpec matcher to with, and contain_exactly(1, 2, 3) does exactly what you want, so you can pass that to with:

expect(calculation_service).to receive(:sum?).with(contain_exactly(1, 2, 3)) { 6 }

However, "with contain exactly 1, 2, 3" doesn't read very well (and the failure message will be similarly grammatically awkward), so RSpec 3 provides aliases that solve both problems. In this case, you can use a_collection_containing_exactly:

expect(calculation_service).to receive(:sum?).with(
a_collection_containing_exactly(1, 2, 3)
) { 6 }

Stubbing array responses with rspec

How about creating a class which handles the needed interface:

class DBStub
def initialize(data_store)
@data_store = data_store
end

def [](arg1, arg2)
@data_store[arg1][arg2]
end
end

ws = DBStub.new(temp)

Check if two arrays have the same contents (in any order)

This doesn't require conversion to set:

a.sort == b.sort

Need to sort array based on another array of array

I assume you want to sort the elements in a according to their position in b and that the elements in b are the strings 'A', 'B', etc and not constants.

Then I would do something like this:

a = [["A", 1075000], ["C", 1750000], ["D", 0], ["E", 0], ["B", 0]]
b = ['A','B','C','D','E']

a.sort { |x, y| b.index(x.first) <=> b.index(y.first) }
#=> [["A", 1075000], ["B", 0], ["C", 1750000], ["D", 0], ["E", 0]]

Depending on the size of b it might make sense to use sort_by instead of sort. sort_by catches the return value of the block and does not evaluate the block multiple times:

a.sort_by { |x| b.index(x) }

How do I replace repetitive elements in an array matching another array?


array_main.map { |e| array_second.include?( e ) ? 0 : e }

And if you drop that requirement about replacing with 0, you can simply write

array_main - array_second

How to match hashes that contain arrays ignoring order of array elements?

I'd write a custom matcher:

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

Are the elements of an array within the range of another array


array_a = [50,13,25,35,45]
array_b = [14,45]
array_a.max >= array_b.max && array_a.min <= array_b.min
# => true

Edit: Babai's solution is slightly faster and more elegant, I think.

Edit: So most efficient solution is:

array_a = [50,13,25,35,45]
array_b = [14,45]
min,max = array_a.minmax
array_b.all? {|num| num<=max && num>=min }
# => true


Related Topics



Leave a reply



Submit