Проверьте, можно ли сортировать массив - PullRequest
0 голосов
/ 24 августа 2018

Есть ли способ избежать этой ошибки при сортировке массива?

 ArgumentError: comparison of Hash with Hash failed

Я ищу что-то вроде этого:

a.sort if a.is_sortable?

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

Сортировка обычно основана на Comparable:

Миксин Comparable используется классами, чьи объекты могут быть упорядочены. Класс должен определять оператор <=>, который сравнивает получателя с другим объектом, возвращая -1, 0 или +1 в зависимости от того, меньше ли получатель, равен или больше другого объекта.

чтобы вы могли посмотреть на:

a.grep(Comparable)

и посмотрите, имеет ли он ту же длину, что и a. Или вы можете сказать:

a.all? { |e| e.is_a? Comparable } 

Но вам действительно не нужны все Comparable для #sort для работы, вам просто нужен метод <=>, чтобы вы могли сказать:

a.all? { |e| e.respond_to? :<=> }

Конечно, все вышеперечисленное предполагает, что все элементы a одинаковы для <=> (т. Е. x <=> y работает для любых двух записей x и y из a ) и это не обязательно так, даже если все элементы a равны Comparable s или даже если они все отвечают на <=>. Мы также предполагаем, что <=> реализован правильно, но если у вас плохая реализация оператора космического корабля, тогда все ставки в любом случае отключены.

Для произвольного массива a единственный способ определить, можно ли его отсортировать, - это попытаться отсортировать его и посмотреть, не взорвется ли он. Для массивов, в которых вы немного больше знаете об элементах (т.е. все элементы являются экземплярами одного и того же класса), у вас есть несколько вариантов.

0 голосов
/ 24 августа 2018

Краткий ответ: нет, метод is_sortable? отсутствует.

Длинный ответ: sort использует оператор <=>, поэтому вы можете проверить, определен ли он:

a.sort if a.all? { |item| item.respond_to?(:<=>) }

Однако он определен для хэшей, потому что они наследуются от Kernel:

{}.respond_to?(:<=>) # => true
{}.method(:<=>) # => #<Method: Hash(Kernel)#<=>>

Но, когда вы пытаетесь использовать его для хэшей, вы обычно получаете обратно nil, что вызывает исключение:

# No idea why this should work:
{} <=> {} # => 0
{a: :b} <=> {c: :d} # => nil

Так что, вероятно, лучше использовать вместо него sort_by и придумать собственный алгоритм сортировки, который может обрабатывать хэши.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...