Как отсортировать массив ruby ​​в порядке возрастания, но оставить ноль последним - PullRequest
2 голосов
/ 25 марта 2011

Я пытаюсь отсортировать массив Ruby с помощью следующей функции

@prices = @item.prices.sort { |x,y| x.total <=> y.total }

, которая заказывает от самой низкой до самой высокой стоимости.Тем не менее, некоторые продукты имеют всего 0,00, и я хочу, чтобы они появлялись последними, а не наверху.

Я попробовал несколько вещей, но хотел бы каким-то образом изменить этот блок, чтобы отсортировать ноль внизу, но сохранитьостальное в порядке возрастания.

Спасибо.

Ответы [ 5 ]

3 голосов
/ 25 марта 2011

Попробуйте, я думаю, что он делает то, что вы просите:

@prices = @item.prices.sort {|a,b| a.total==0 ? 1 : b.total==0 ? -1 : a.total<=>b.total}
2 голосов
/ 25 марта 2011

Только для записи:

>> a = [0, 1, 3, 0, 2, 5, 0, 9]
=> [0, 1, 3, 0, 2, 5, 0, 9]
>> a.sort_by { |x| x.zero? ? Float::MAX : x }
=> [1, 2, 3, 5, 9, 0, 0, 0]

На большинстве платформ 1.0/0 оценивается как Infinity, поэтому вы также можете использовать это вместо Float::MAX:

>> b = [1,4,2,0,5,0]
=> [1, 4, 2, 0, 5, 0]
>> Inf = 1.0/0
=> Infinity
>> b.sort_by { |x| x.zero? ? Inf : x }
=> [1, 2, 4, 5, 0, 0]
2 голосов
/ 25 марта 2011
prices = [0, 1, 2, 0,4, 3]
prices = prices.sort_by do |price|
  [
    if price == 0
      1
    else
      0
    end,
    price
  ]
end
p prices
# => [1, 2, 3, 4, 0, 0]

Хитрость в том, что массивы сравниваются путем сравнения их первых элементов, но если эти элементы равны, то путем сравнения их следующих элементов и так далее.Таким образом, наличие в блоке sort_by массива позволяет вам определить первичный порядок сортировки, вторичный порядок сортировки и т. Д. В чистом виде.

1 голос
/ 25 марта 2011

Так что для этого придумайте компаратор ...

if x.total == 0
  # always consider 0 "largest" and no 0 can be larger than another
  # (make sure 0.0 is 0 and not a number really close to 0)
  # perhaps x or y should be first for other reasons as well?
  1
else
  # otherwise lower to higher as normal
  x.total <=> y.total
end

Или без комментариев:

foo.sort {|x, y| if x.total == 0 then 1 else x.total <=> y.total end}

Удачного кодирования.

0 голосов
/ 28 марта 2011

Мне бы это показалось менее хакерским и менее доступным только для записи:

prices = prices.sort_by do |price| 
  zero_status = price.zero? ? 1 : 0
  [zero_status, price]
end

, потому что это идиоматический способ сортировки чего-либо по двум критериям, что вы здесь делаете.

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