Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort an array of ints and strings? [duplicate]

I am trying to sort an array with a mixture of ints and strings. Take for example:

a = ["a", "b", 5, "c", 4, "d", "a1", "a12", 3, 13, 2, "13a", "12a"]

I tried:

a.sort do |x, y|
  if x.class == y.class
    x <=> y
  else
    x.class.to_s <=> y.class.to_s
  end
end

Which returns:

[2, 3, 4, 5, 13, "12a", "13a", "a", "a1", "a12", "b", "c", "d"]

The outcome I want is:

[2, 3, 4, 5, "12a", 13, "13a", "a", "a1", "a12", "b", "c", "d"]
like image 397
Christian Fazzini Avatar asked Jan 15 '16 14:01

Christian Fazzini


People also ask

Does Counting Sort deal well with duplicates?

A simple solution would be to use efficient sorting algorithms like Merge Sort, Quicksort, Heapsort, etc., that can solve this problem in O(n. log(n)) time, but those will not take advantage of the fact that there are many duplicated values in the array. A better approach is to use a counting sort.


1 Answers

a.sort_by { |x| [(x.to_s.match(/^\d+/) ? x.to_i : 1.0 / 0), x.to_s] }

The idea is to sort first by the numeric value and secondly by the string value. If the the string doesn't start with numeric value, forcefully consider the numeric value to be infinity.


EDIT: As OP has clarified that he wants to consider not just the leading numeric value, but all that follow, we can use the same idea, just this time we have to apply it on each individual numeric and non-numeric entity in the string:

a.sort_by do |x|
  x.to_s.split(/(\D+)/).map do |y|
    [(y.match(/\d/) ? y.to_i : 1.0 / 0), y]
  end
end
like image 72
ndnenkov Avatar answered Sep 30 '22 10:09

ndnenkov