Reputation: 382
I am working on ruby on rails and i am new here as well ruby on rails. I am working on one project and find some issue of sorting an array of string which contains images name. I have tried many algorithm which i know doesn't help me. When i call service for image extraction it gives me like this array.
Example:
["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"]
I want to sort this array like this:
["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"]
I had tried many things to sort but can't get any solutions. please help me.
Upvotes: 3
Views: 494
Reputation: 36110
names.sort_by { |name| name.scan(/\d+/).map(&:to_i) }
This finds all numbers in each file name and sorts by said numbers. Note that arrays are ordered by comparing the first element, in case of equality - the second and so on.
Upvotes: 10
Reputation: 110755
For the given array, arr
, here's an off-the-wall solution.
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"]
Note that
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>]
Upvotes: 2
Reputation: 54303
If you know that the number of pages is bounded (e.g. less than 1000), this method has the advantage of sorting alphabetically and numerically :
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
Here are the temporary strings that are being sorted :
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
Upvotes: 2