Как отсортировать заданный список массивов?

#ruby #sorting #natural-sort

#ruby #сортировка #естественная сортировка

Вопрос:

 list = ["HM00", "HM01", "HM010", "HM011", "HM012", "HM013", "HM014", "HM015", "HM016", "HM017", "HM018", "HM019", "HM02", "HM020", "HM021", "HM022", "HM023", "HM024", "HM025", "HM026", "HM027", "HM028", "HM029", "HM03", "HM030", "HM031", "HM032", "HM033", "HM034", "HM035", "HM036", "HM037", "HM038", "HM039", "HM04", "HM040", "HM041", "HM042", "HM043", "HM044", "HM045", "HM046", "HM047", "HM05", "HM06", "HM07", "HM08", "HM09"]
  

Я хочу отобразить результаты как [«HM00», «HM01», «HM002» …], но используя метод сортировки, он выдает следующие результаты

 ["HM00", "HM01", "HM010", "HM011", "HM012", "HM013", "HM014", "HM015", "HM016", "HM017", "HM018", "HM019", "HM02"]
  

Комментарии:

1. Все ли значения содержат ‘HM’ или у вас могут быть и другие значения?

2. Да, содержит HM

3. Вы получаете этот результат, потому что элементы вашего массива отсортированы буквенно-цифровым способом.

Ответ №1:

Если каждый элемент имеет номер в конце

 list.sort_by { |item| item.scan(/d*$/).first.to_i }
  

сопоставьте это число в конце, возьмите первое (потому что сканирование дает вам массив результатов), преобразуйте его в целое число

проще

 list.sort_by { |item| item[/d*$/].to_i }
  

[] уже выполняется первое совпадение

Ответ №2:

Существует более общее решение, которое будет работать с большинством строк, содержащих группы чисел

 number = /([ -]{0,1}d )/;

strings = [ '2', '-2', '10', '0010', '010', 'a', '10a', '010a', '0010a', 'b10', 'b2', 'a1b10c20', 'a1b2.2c2' ]

p strings.sort_by { |item| [item.split(number).each_slice(2).map {
  |x| x.size == 1 ? [ x[0], '0' ] : [ x[0], x[1] ] }].map {|y| ret = y.inject({r:[],x:[]}) { |s, z| s[:r].push [ z[0], z[1].to_r]; s[:x].push z[1].size.to_s; s }; ret[:r]   ret[:x] }.flatten
}
  

Вы можете настроить number в соответствии с типами чисел, которые вы хотите использовать: целые числа, с плавающей запятой и т.д.

Существует некоторый дополнительный код для сортировки равных чисел по длине, чтобы ’10’ предшествовало ‘010’.