rspec ожидает сравнения двух хэшей, исключающих указанные ключи

#ruby #rspec

#ruby #rspec

Вопрос:

Существует ли какая-либо ожидаемая спецификация, которая будет сравнивать два хэша, исключая только указанные ключи.

 H1 = {'name' => 'XXXXx', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
H2 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
  

Сравните два вышеупомянутых хэша, исключив только ключ DOB.

Комментарии:

1. Hash#values_at и match_array ожидание?

2. values_at вернет массив значений, основанный на ключах, указанных в values_at. Но я хочу исключить только определенный набор ключей

3. Hash#reject затем.

4. Имена разные ( "XXXXX" и "XXXXx" )? Или это опечатка?

5. Нет, это обдумано. Отныне я должен получить результат, поскольку имя отличается на H2 при сравнении с H1

Ответ №1:

Я не понимаю, зачем вам это нужно, но вы можете использовать Hash#delete_if

 RSpec.describe do
  let(:hash1) { {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'} }
  let(:hash2) { {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'} }

  it 'should correctly compare two subhashes' do
    expect(hash1.delete_if { |k,_| k == 'DOB' }).to eql(hash2.delete_if { |k,_| k == 'DOB' })
  end
end
  

Если вы хотите сделать свой expect более аккуратным, вы можете преобразовать хэши раньше.

Также вы можете использовать Hash#reject

 RSpec.describe do
  it 'should correctly compare two subhashes' do
    hash1 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
    hash2 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
    hash1, hash2 = [hash1, hash2].map { |h| h.reject { |k,_| k == 'DOB' } }

    expect(hash1).to eql(hash2)
  end
end
  

Комментарии:

1. Я думаю, вы ошибочно приняли ‘DOB’ за ‘name’.

2. @sawa, спасибо. Я заметил, что имена разные ( "XXXXX" и "XXXXx" ) и ввел себя в заблуждение..

3. Не было бы удобно иметь метод хэша delete2 , такой { a:1, b:2, c:3, d:4 }.delete2(:b, :d) #=> { a:1, c:3 } , чтобы без изменения получателя?

4. @CarySwoveland Хорошая идея. Выглядит красиво. Возможно, когда-нибудь появятся в Ruby.

Ответ №2:

Вместо сравнения двух временных хэшей, которые равны H1 и H2 с удаленным ключом 'DOB' (если присутствует), можно сравнить два временных хэша, которые имеют ключи 'DOB' с одинаковым значением. Это значение произвольно; я использовал nil .

 expect(H1.merge('DOB'=>nil).to eq(H2.merge('DOB'=>nil)))
  

Другой способ:

 expect((H1.keys|H2.keys).all? do |k| 
  k=='DOB' || (H1.key?(k) amp;amp; H2.key?(k) amp;amp; H1[k]==H2[k])
end.to eq(true)
  

H1.key?(k) amp;amp; H2.key?(k) существует ли на случай, если один из хэшей имеет ключ k со значением nil , а другой хэш не имеет ключа k .

Это имеет преимущество в том, что у него более скромные требования к памяти, чем у двух подходов, о которых я упоминал выше.

Комментарии:

1. Асимметрия уменьшает красоту. Я думаю, вы можете просто объединить {'DOB' => nil} оба хэша.

2. @sawa, согласен. Я внес изменения. Спасибо.

3. Вы должны переключить приемник и аргумент для слияния относительно H1. В противном случае, если у H1 было значение для DOB, отличное от nil, …

4. Будем надеяться, что я, наконец, понял это правильно. 🙂 (Обратите внимание, что у моих смайликов есть носы.)