Ruby:按字母顺序对字符串数组进行排序,包括一些字符串数组

时间:2014-02-21 23:29:55

标签: ruby arrays string sorting enumeration

说我有:

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

我希望按以下方式排序:

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

我明白了:

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

我真正想要按字母顺序排列项目,数组项目在第一个元素上排序:

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

或者,最好是,我想:

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

如果示例不够清楚,我希望按字母顺序对项目进行排序。

有关如何到达那里的任何建议吗?

到目前为止,我已经尝试了一些东西但似乎无法实现它。感谢。

7 个答案:

答案 0 :(得分:3)

我认为这就是你想要的:

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

答案 1 :(得分:3)

我愿意

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

答案 2 :(得分:1)

你真的很亲密。只需将.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"]

答案 3 :(得分:1)

a.map { |b| b.is_a?(Array) ? b.join(', ') : b }.sort

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

答案 4 :(得分: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"]

答案 5 :(得分: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指出sortsort_by慢得多,并给出了解释原因的参考。我一直想知道如何使用Benchmark module,所以借此机会比较手头问题的两种方法。我使用@ Rafa的解决方案sort_by和我的sort

为了进行测试,我提前构建了一个包含100个随机样本(每个样本有10,000个随机元素)的数组,因此基准测试不包括构建样本所需的时间(这并不是无关紧要的)。 10,000个元素中的8,000个是8个小写字母的随机字符串。其他2,000个元素是[str1, str2]形式的2元组,其中str1str2都是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's 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将行标签作为参数。

答案 6 :(得分:0)

对扁平数组进行排序

如果您只希望嵌套数组的所有元素展平,然后按字母顺序排序,那么您需要做的只是flattensort。例如:

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