сортировка по новому полю - PullRequest
0 голосов
/ 08 января 2012

Итак, у меня есть массив событий, которые я заказал, вызвав sort

all.sort {|a,b| b.time<=> a.time}

Теперь недавно я добавил новое поле в мой объект, чтобы включить время "uploaded_at". Я хотел бы сначала отсортировать по «времени», а затем по времени «Uploaded_at» (так как поле «время» - это просто дата без какого-либо времени.

Мне нужно помнить, что все старые «События» не будут иметь значения для «Uploaded_at», и поэтому этот метод не может существовать. Как я могу пойти об этом? (Меня не волнует порядок двух событий, которые имеют одинаковое время и не имеют значений uploaded_at

Ответы [ 2 ]

2 голосов
/ 08 января 2012

Попробуйте что-то вроде этого:

all.sort_by { |x| [x.time, (x.uploaded_at rescue Time.utc(1970))] }
1 голос
/ 08 января 2012

Вам придется обрабатывать значения nil в uploaded_at с некоторой осторожностью. Проблема в том, что x <=> nil и nil <=> x будут nil, кроме случаев, когда x.nil?, а для сортировки требуется оператор <=>, чтобы вернуть Fixnum.

Один из вариантов - сопоставить nil s с некоторыми значениями, отличными от nil, которые всегда будут правильно сортироваться, Time.new(0) возможно:

all.sort_by { |a| [a.time, a.uploaded_at || Time.new(0)] }

Array#<=> операторы компонент за компонентом, и вышеизложенное устраняет проблему nil. Если вы хотите nil s на другом конце, тогда выберите что-то большое вместо Time.new(0).

Другой вариант - обрабатывать nil s вручную:

all.sort do |a, b|
    x = a.time <=> b.time
    if(x != 0)
        x
    elsif(a.uploaded_at.nil? && b.uploaded_at.nil?)
        0
    elsif(a.uploaded_at.nil?)
        1
    elsif(b.uploaded_at.nil?)
        -1
    else
        a.uploaded_at <=> b.uploaded_at
    end
end

Вы, конечно, отрегулируете ветви elsif(a.uploaded_at.nil?) и elsif(b.uploaded_at.nil?), чтобы поставить nil s там, где вы хотите.

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