Как отсортировать массив целых и строк?

Я пытаюсь отсортировать массив со смесью целых и строк. Взять, к примеру:

a = ["a", "b", 5, "c", 4, "d", "a1", "a12", 3, 13, 2, "13a", "12a"]

Я старался:

a.sort do |x, y|
  if x.class == y.class
    x <=> y
  else
    x.class.to_s <=> y.class.to_s
  end
end

Который возвращает:

[2, 3, 4, 5, 13, "12a", "13a", "a", "a1", "a12", "b", "c", "d"]

Результат, который я хочу:

[2, 3, 4, 5, "12a", 13, "13a", "a", "a1", "a12", "b", "c", "d"]

1 ответ

Решение
a.sort_by { |x| [(x.to_s.match(/^\d+/) ? x.to_i : 1.0 / 0), x.to_s] }

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


РЕДАКТИРОВАТЬ: Как OP пояснил, что он хочет рассмотреть не только начальное числовое значение, но и все, что следует, мы можем использовать ту же идею, только на этот раз мы должны применить ее к каждой отдельной числовой и нечисловой сущности в строке:

a.sort_by do |x|
  x.to_s.split(/(\D+)/).map do |y|
    [(y.match(/\d/) ? y.to_i : 1.0 / 0), y]
  end
end
Другие вопросы по тегам