Sorting an Array of Strings in Ruby

Sorting an array of strings in Ruby

Both lines do the same (create a new array, which is reverse sorted). The main argument is about readability and performance. array.sort.reverse! is more readable than array.sort{|x,y| y<=>x} - I think we can agree here.

For the performance part, I created a quick benchmark script, which gives the following on my system (ruby 1.9.3p392 [x86_64-linux]):

                              user     system      total        real
array.sort.reverse 1.330000 0.000000 1.330000 ( 1.334667)
array.sort.reverse! 1.200000 0.000000 1.200000 ( 1.198232)
array.sort!.reverse! 1.200000 0.000000 1.200000 ( 1.199296)
array.sort{|x,y| y<=>x} 5.220000 0.000000 5.220000 ( 5.239487)

Run times are pretty constant for multiple executions of the benchmark script.

array.sort.reverse (with or without !) is way faster than array.sort{|x,y| y<=>x}. Thus, I recommend that.


Here is the script as a Reference:

#!/usr/bin/env ruby
require 'benchmark'

Benchmark.bm do|b|
master = (1..1_000_000).map(&:to_s).shuffle
a = master.dup
b.report("array.sort.reverse ") do
a.sort.reverse
end

a = master.dup
b.report("array.sort.reverse! ") do
a.sort.reverse!
end

a = master.dup
b.report("array.sort!.reverse! ") do
a.sort!.reverse!
end

a = master.dup
b.report("array.sort{|x,y| y<=>x} ") do
a.sort{|x,y| y<=>x}
end
end

Sort array of string with digits and characters in ruby

You're looking for a "natural" sort where the numeric substrings will be compared as numbers as the non-numeric parts will be compared like strings. Conveniently enough, arrays in Ruby compare element-by-element and your format is fairly regular so you can get away with a #sort_by call and a bit of mangling to convert "12mo-21-classic" to [12, 'mo-', 21, '-classic']. Something like this for example:

# This is a bit complicated so we'll give the logic a name.
natural_parts = ->(s) { s.match(/(\d+)(\D+)(\d+)(\D+)/).to_a.drop(1).map.with_index { |e, i| i.even?? e.to_i : e } }
array.sort_by(&natural_parts)

Custom Sort array of strings by another array of strings - Ruby

I assume that:

  • every element of list is in sort_order;
  • sort_order may contain elements that are not in list;
  • list may contain duplicates; and
  • sort_order contains no duplicates.

If sort_order initially contains duplicates the temporary array sort_order.uniq can be used in the calculations.

Observe that if, as in the example, list contains no duplicates and sort_order contains no elements other than those in list, sorting list by the order of its elements in sort_order is trivial, as it merely returns sort_order.

The following is more efficient than methods that use sort or sort_by (O(n) versus O(n*log(n)) computational complexity.)

list = ["gold", "copper", "silver", "copper", "steel", "gold"]
sort_order = ["bronze", "silver", "tin", "gold", "copper", "steel"]

count = list.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
#=> {"gold"=>2, "copper"=>2, "silver"=>1, "steel"=>1}
sort_order.flat_map { |e| [e]*count[e] }.reject(&:empty?)
#=> ["silver", "gold", "gold", "copper", "copper", "steel"]

How to sort an array of strings containing numbers and letters in ruby

array.sort_by { |item|
number, letter = *item.split
[letter, number.to_i]
}

Arrays compare as their first element; in case an element is equal, next element is compared.

Efficient way to sort an array of numbers and string in ruby?

One way is to partition your array by those elements being Integer, to make sure they remain first and then sort the elements of each array:

[4,2,'b',5,'c','a',7].partition { |e| e.is_a?(Integer) }.flat_map(&:sort)
# [2, 4, 5, 7, "a", "b", "c"]

How do I sort a Ruby array of strings by length?

arr = arr.sort_by {|x| x.length}

Or in 1.8.7+:

arr = arr.sort_by(&:length)

Sort an Array of Strings by their Integer Values

I'll throw another method out there since it's the shortest way I can think of

a.sort_by(&:to_i)


Related Topics



Leave a reply



Submit