Повторно откройте класс Set
Вы можете создать небольшой синтаксис c сахар, повторно открыв класс Set и добавив пару служебных методов. Уловка действительно заключается в обработке крайних случаев, таких как объекты, которые не отвечают на #downcase (например, Integer, Float или NilClass). Например, используя Ruby 2.7.1:
class Set
def difference! other_set
s1 = downcase self
s2 = downcase other_set
s1 - s2
end
protected
def downcase set
set.map { _1.respond_to?(:downcase) ? _1.downcase : _1 }
end
end
В следующих примерах используется модифицированный класс Set для иллюстрации некоторых типичных результатов:
Set[:A, :B, :C].difference! Set[:a, :B]
#=> [:c]
Set[:A, :B, :C, 1, nil].difference! Set[:a, :B]
#=> [:c, 1, nil]
Set[:A, :b, :c, 1, nil, 'foo'].difference! Set[:a, :B, "FOO"]
#=> [:c, 1, nil]
Если вы предпочитаете использовать #upcase вместо этого установленная разница возвращает :C
вместо :c
, go прямо вперед. Точно так же, если вы действительно предпочитаете использовать Set#difference_insensitive
вместо Set#difference!
, вы, безусловно, можете. Мне больше нравится использовать метод взрыва для этого варианта использования, но именование вещей - это другое сложная вещь в информатике.
Предостережения
Сравнения может быть сложно. Независимо от того, используете вы верхний или нижний регистр, результаты потенциально могут быть наполовину неверными, поскольку символы верхнего и нижнего регистра - это разные объекты. Поскольку :A
и :a
- это две разные метки с двумя разными регистрами символов, какой из них он должен возвращать как «другой» символ?
Он также не работает, как можно было бы ожидать от многосимвольных метки или объекты String, когда преобразование верхнего или нижнего регистра приводит к отсутствию различий. Например, следующее верно, но не интуитивно понятно, потому что все значения преобразуются в :foobar
.
Set[:foobar, :fooBar, :fOoBaR].difference! Set[:FOOBAR, :foobar]
#=> []
Это может иметь отношение или не иметь отношения к вашему варианту использования. Однако, даже если это сработало, все равно возникает вопрос о том, какое написание idosyncrati c должно быть возвращено при сравнении регистров символов.
В зависимости от ваших реальных данных вам может потребоваться копаться в Установите # compare_by_identity , Set # classify и Comparable для различных способов определения / сравнения ваших данных Set способами, которые могут обойти эту проблему. Если вы go этот маршрут, вам также может потребоваться повторно открыть класс Set для определения <=>
, но по сути не очевидно, как лучше всего реализовать это, если у вас нет четких ожиданий насчет как вы планируете сравнивать разнородные объекты за пределами примеров данных, которые вы разместили в исходном вопросе.