2009-05-24 5 views
3

Приносим извинения, если это было ответили раньше или очевидно ... сделал некоторые поиски здесь и в Goog и не смог найти ответ.Сортировка объектов по булевым значениям в Ruby

Я ищу сортировку массива поставщиков по цене и являются ли они предпочтительным_провайдером? (Истина или ложь)

Например, в array p of Providers ...

p1.price == 1, p1.preferred_provider? == false 
p2.price == 2, p2.preferred_provider? == true 
p2.price == 3, p3.preferred_provider? == true 

Я хотел бы p.sort_by и получить:

[p2 p3 p1] 

IAW

p.sort_by {|x| x.preferred_provider?, x.price } 

не работает и получает ...

undefined method `<=>' for false:FalseClass 

Любые предложения по лучшим способам решения этой проблемы?

+0

Фактически у вас почти было: p.sort_by {| x | [X.preferred_provider? ? 0: 1, x.price]}. –

+0

А ... хорошо. рефакторинг кандидата. Благодарю. –

ответ

7

Большинство языков обеспечивают функции сортировки, которые принимают comparators для такого рода вещь. В Ruby это просто массив. Сорт:

p.sort {|a, b| if (a.preferred_provider? == b.preferred_provider? 
       then a.price <=> b.price 
       elsif a.preferred_provider? 
        1 
       else -1 
     } 
+0

Эта логика не возвращает правильный порядок, но он поместил меня на правильный путь, используя a.preferred_provider? == b.preferred_provider? и реверсирование 1 и -1. спасибо –

+1

К сожалению, вы бы хотели использовать == там (теперь исправлено). Чтобы выработать бит, замыкание должно возвращать положительное число, если a приходит после b, отрицательное число, если a - до b, и 0, если они равны для сортировки. Таким образом, простая реализация для сортировки числовых значений - {| a, b | a - b}. –

3

Вы можете определить <=>Provider на классе, чтобы делать то, что вы хотите, а затем отсортировать с помощью Array.sort метода (а не Enumerable.sort_by). Вот определение <=>, что я взбитое:

class Provider 
    def <=>(other) 
    if preferred_provider? 
     if other.preferred_provider? 
     @price <=> other.price 
     else 
     1 
     end 
    else 
     if other.preferred_provider? 
     -1 
     else 
     @price <=> other.price 
     end 
    end 
    end 
end 

Тогда, если у вас есть массив p, вы можете просто сделать p_sorted = p.sort.

(Обратите внимание, что я не проверял этот код, так что может быть несколько ошибок, но я думаю, что она служит для демонстрации идеи.)

+0

Это сработало бы, но другое решение было более подходящим для моей проблемы по причинам, которые я не указал в исходном вопросе. Спасибо ... очень ценю. –

Смежные вопросы