Прежде всего, ваш my_array
- это JavaScript / JSON, поэтому я предполагаю, что у вас действительно есть это:
my_array = [
{"id" => "some-server-1", "foo" => "bar"},
{"id" => "some-server-2", "foo" => "bat"},
{"id" => "some-server-10", "foo" => "baz"}
]
Тогда вам просто нужно sort_by
числовой суффикс значений 'id'
:
my_array.sort_by { |e| e['id'].sub(/^some-server-/, '').to_i }
Если префиксы "some-server-" не всегда являются "some-server-", то вы можете попробовать что-то вроде этого:
my_array.sort_by { |e| e['id'].scan(/\D+|\d+/).map { |x| x =~ /\d/ ? x.to_i : x } }
Это разделит значения 'id'
на числовые и нечисловые части, преобразует числовые части в целые числа, а затем сравнивает смешанные массивы строк / целых чисел, используя оператор Array <=>
(который сравнивает по компонентам);это будет работать до тех пор, пока числовые и нечисловые компоненты всегда совпадают.Этот подход будет обрабатывать это:
my_array = [
{"id" => "some-server-1", "foo" => "bar"},
{"id" => "xxx-10", "foo" => "baz"}
]
, но не это:
my_array = [
{"id" => "11-pancakes-23", "foo" => "baz"},
{"id" => "some-server-1", "foo" => "bar"}
]
Если вам нужно обработать этот последний случай, вам нужно будет сравнивать массивы entry-by-entryот руки и настройте сравнение на основе того, что у вас есть.Вы все еще можете получить некоторые из преимуществ sort_by
Schwartzian Transform с чем-то вроде этого (не очень хорошо проверенный код):
class NaturalCmp
include Comparable
attr_accessor :chunks
def initialize(s)
@chunks = s.scan(/\D+|\d+/).map { |x| x =~ /\d/ ? x.to_i : x }
end
def <=>(other)
i = 0
@chunks.inject(0) do |cmp, e|
oe = other.chunks[i]
i += 1
if(cmp == 0)
cmp = e.class == oe.class \
? e <=> oe \
: e.to_s <=> oe.to_s
end
cmp
end
end
end
my_array.sort_by { |e| NaturalCmp.new(e['id']) }
БазовыйИдея здесь состоит в том, чтобы перенести шум сравнения в другой класс, чтобы предотвратить превращение sort_by
в непонятный беспорядок.Затем мы используем то же сканирование, что и раньше, чтобы разбить строки на части и реализовать компаратор массива <=>
вручную.Если у нас есть две вещи одного и того же класса, тогда мы разрешим этому классу <=>
разобраться с этим, в противном случае мы вынуждаем оба компонента в String и сравниваем их как таковые.И нам важен только первый результат, отличный от 0.