2017-02-22 7 views
3

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

Пример:

["page-1_1.png", 
"page-1_10.png", 
"page-1_11.png", 
"page-1_2.png", 
"page-1_3.png", 
"page-1_4.png", 
"page-1_5.png", 
"page-1_6.png", 
"page-1_7.png", 
"page-1_8.png", 
"page-1_9.png"] 

Я хочу, чтобы отсортировать этот массив так:

["page-1_1.png", 
"page-1_2.png", 
"page-1_3.png", 
"page-1_4.png", 
"page-1_5.png", 
"page-1_6.png", 
"page-1_7.png", 
"page-1_8.png", 
"page-1_9.png", 
"page-1_10.png", 
"page-1_11.png"] 

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

+0

Возможный дубликат [Как отсортировать буквенно-цифровой массив в рубине] (http://stackoverflow.com/questions/5480703/how-to-sort-an-alphanumeric-array-in-ruby) –

+0

Когда вы приводите пример (как правило, хорошо) полезно назначить переменную для каждого входного объекта (например, 'arr = [" page-1_1.png ", ...]'). Таким образом, читатели могут ссылаться на эти переменные в ответах и ​​комментариях, не определяя их. Более того, все читатели будут ссылаться на одни и те же переменные, что также полезно. –

ответ

10
names.sort_by { |name| name.scan(/\d+/).map(&:to_i) } 

Это находит все номера в каждом имени файла и сортирует по сказал числа. Обратите внимание, что массивы упорядочиваются путем сравнения первого элемента, в случае равенства - второго и т. Д.

+1

Большое спасибо @ndn. – sam

+0

@sam, если этот ответ сработал для вас, вы должны отметить его как правильный ответ, иначе этот вопрос будет отмечен как «без ответа» в результатах поиска на сайте. – eiko

+0

Хороший ответ, ✅. В качестве пояснения может оказаться полезным показать возвращаемые значения для 'names.map {| name | name.scan (/ \ d + /)} 'и' names.map {| name | name.scan (/ \ d + /). map (&: to_i)} 'и объясните, что вы сравниваете массивы. –

2

Для данного массива, arr, здесь находится решение для установки на стене.

require 'ipaddr' 

arr.sort_by { |s| IPAddr.new(s.gsub(/\D/) { |c| c == '_' ? '.' : '' } + '.0.0') } 
    #=> ["page-1_1.png", 
    # "page-1_2.png", 
    # "page-1_3.png", 
    # "page-1_4.png", 
    # "page-1_5.png", 
    # "page-1_6.png", 
    # "page-1_7.png", 
    # "page-1_10.png", 
    # "page-1_11.png", 
    # "page-3_92.png", 
    # "page-11_8.png"] 

Обратите внимание, что

arr.map { |s| IPAddr.new(s.gsub(/\D/) { |c| c == '_' ? '.' : '' } + '.0.0') } 
    #=> [#<IPAddr: IPv4:1.1.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.10.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.11.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.2.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.3.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.4.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.5.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.6.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:1.7.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:11.8.0.0/255.255.255.255>, 
    # #<IPAddr: IPv4:3.92.0.0/255.255.255.255>] 
+0

Это, вероятно, не желаемое поведение. '% w (1_35 12_0 2_0) .sort_by {| s | s.delete ('_') [/ \ d + /]. to_i} ' –

+0

@ Эрик, да, конечно. Благодарю. В любом случае я исправил это тем, что, по моему мнению, является лучшим подходом. –

+0

Извините, все еще не нужно. '1_10' и' 1_1' обрабатываются одинаково, а '1_11' должен быть после' 1_7' –

2

Если вы знаете, что число страниц ограничено (например, менее 1000), этот метод имеет преимущество сортировки в алфавитном порядке и численно:

arr = 
    ['page-1_1.png', 
    'page-1_10.png', 
    'page-1_11.png', 
    'page-1_3.png', 
    'page-1_9.png'] 

puts arr.sort_by{ |str| str.gsub(/\d+/){ |number| number.rjust(3, '0') } } 
# page-1_1.png 
# page-1_3.png 
# page-1_9.png 
# page-1_10.png 
# page-1_11.png 

puts %w(b c a).sort_by{ |str| str.gsub(/\d+/){ |number| number.rjust(3, '0') } } 
# a 
# b 
# c 

Ниже перечислены временные строки, которые сортируются:

puts arr.map{ |str| str.gsub(/\d+/){ |number| number.rjust(3, '0') } } 
# page-001_001.png 
# page-001_010.png 
# page-001_011.png 
# page-001_003.png 
# page-001_009.png