1
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"]

I want the display the results as ["HM00","HM01","HM002"...] but using sort method it is giving the below results

["HM00", "HM01", "HM010", "HM011", "HM012", "HM013", "HM014", "HM015", "HM016", "HM017", "HM018", "HM019", "HM02"]
3
  • Do all the values contain 'HM' or you might have other values too ? Commented Apr 11, 2019 at 8:01
  • Yes contains HM Commented Apr 11, 2019 at 8:05
  • You're getting that result because your array items are sorted alphanumerically. Commented Apr 11, 2019 at 8:08

2 Answers 2

5

If every element has a number at the end

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

match that number at the end, take the first one (because scan gives you an array of results), convert it to an integer

simpler

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

[] already takes the first match

Sign up to request clarification or add additional context in comments.

Comments

0

There is a more general solution that will work with most strings that contain groups of numbers

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
}

You can adjust number to match the types of numbers you want to use: integers, floating point, etc.

There is some extra code to sort equal numbers by length so that '10' comes before '010'.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.