Ruby: sorting an array of strings in alphabetical order, including some string arrays

Let's say I have:

a = ["apple", "pear", ["grapes", "berries"], "peach"]

and I want to sort by:

a.sort_by do |f|
  f.class == Array ? f.to_s : f
end

I get:

[["grapes", "berries"], "apple", "peach", "pear"]

Where I really want the elements in alphabetical order, with the array elements sorted by their first element:

["apple", ["grapes", "berries"], "peach", "pear"]

or, preferably, I want:

["apple", "grapes, berries", "peach", "pear"]

If the example is not clear enough, I am looking for sorting the elements in alphabetical order.

Any suggestions on how to get there?

I have tried several things so far, but can't seem to get it there. Thank.

+3
source share
7 answers

I think this is what you want:

a.sort_by { |f| f.class == Array ? f.first : f }
+3
source

I would do

a = ["apple", "pear", ["grapes", "berries"], "peach"]
a.map { |e| Array(e).join(", ") }.sort
# => ["apple", "grapes, berries", "peach", "pear"]
+3
source

. .to_s .first.

irb(main):005:0> b = ["grapes", "berries"]
=> ["grapes", "berries"]
irb(main):006:0> b.to_s
=> "[\"grapes\", \"berries\"]"
irb(main):007:0> b.first
=> "grapes"

:

a.sort_by do |f|
  f.class == Array ? f.first : f
end

:

["apple", ["grapes", "berries"], "peach", "pear"]
+1
a.map { |b| b.is_a?(Array) ? b.join(', ') : b }.sort

# => ["apple", "grapes, berries", "peach", "pear"]
+1

to_s join.

a.sort_by do |f|
  f.class == Array ? f.join : f
end

# => ["apple", ["grapes", "berries"], "peach", "pear"]

:

a.sort_by {|x| [*x].join }

# => ["apple", ["grapes", "berries"], "peach", "pear"]

to_s , , "[":

"[\"grapes\", \"berries\"]"

.

join , :

"grapesberries"

, .

, , , join.

a.map {|x| [*x].join(", ") }.sort

# => ["apple", "grapes, berries", "peach", "pear"]
+1

Array # sort_by - , , Array # sort :

  a.sort do |s1,s2| 
    t1 = (s1.is_a? Array) ? s1.first : s1
    t2 = (s2.is_a? Array) ? s2.first : s2
    t1 <=> t2
  end.map {|e| (e.is_a? Array) ? e.join(', ') : e }
    #=> ["apple", "grapes, berries", "peach", "pear"]  

@theTinMan , sort , sort_by, , , . , Benchmark module, . @Rafa sort_by sort.

100 ( 10 000 , ), , ( ). 8 000 10000 8 . 2000 2- [str1, str2], str1 str2 8 . , .

require 'benchmark'

# n: total number of items to sort
# m: number of two-tuples [str1, str2] among n items to sort
# n-m: number of strings among n items to sort
# k: length of each string in samples
# s: number of sorts to perform when benchmarking

def make_samples(n, m, k, s)
  s.times.with_object([]) { |_, a| a << test_array(n,m,k) }
end

def test_array(n,m,k)
  a = ('a'..'z').to_a 
  r = []
  (n-m).times { r << a.sample(k).join }
  m.times { r << [a.sample(k).join, a.sample(k).join] }
  r.shuffle!
end

# Here what the samples look like:    
make_samples(6,2,4,4)
  #=> [["bloj", "izlh", "tebz", ["lfzx", "rxko"], ["ljnv", "tpze"], "ryel"],
  #    ["jyoh", "ixmt", "opnv", "qdtk", ["jsve", "itjw"], ["pnog", "fkdr"]],
  #    ["sxme", ["emqo", "cawq"], "kbsl", "xgwk", "kanj", ["cylb", "kgpx"]],
  #    [["rdah", "ohgq"], "bnup", ["ytlr", "czmo"], "yxqa", "yrmh", "mzin"]]

n = 10000 # total number of items to sort
m = 2000  # number of two-tuples [str1, str2] (n-m strings)
k = 8     # length of each string
s = 100   # number of sorts to perform

samples = make_samples(n,m,k,s)

Benchmark.bm('sort_by'.size) do |bm|
  bm.report 'sort_by' do
    samples.each do |s|
      s.sort_by { |f| f.class == Array ? f.first : f }
    end
  end

  bm.report 'sort' do
    samples.each do |s| 
      s.sort do |s1,s2| 
        t1 = (s1.is_a? Array) ? s1.first : s1
        t2 = (s2.is_a? Array) ? s2.first : s2
        t1 <=> t2
      end
    end
  end
end

              user     system      total        real
sort_by   1.360000   0.000000   1.360000 (  1.364781)
sort      4.050000   0.010000   4.060000 (  4.057673)

, @theTinMan ! , sort_by sort .

, "" sort_by. sort. 0.010000, , . ( Mac.)

, Benchmark, Benchmark # bm , , ( user system...). bm.report .

+1

, , , , , flatten sort. :

["apple", "pear", ["grapes", "berries"], "peach"].flatten.sort
#=> ["apple", "berries", "grapes", "peach", "pear"]
0
source

All Articles