如何使用sort_by按字母顺序然后按数字顺序然后按特殊字符排序

时间:2020-06-28 11:46:25

标签: ruby-on-rails ruby

我有一个数组:

pecl install mongodb-1.5.0

docker-php-ext-enable mongodb

我需要先使用不区分大小写的字母排序,然后再使用数字后跟特殊字符。

我正在尝试使用arr = ["Bar", "abc", "foo", "1", "20”, "10", "_def"]

sort_by

输出必须为:

irb(main):071:0> arr.sort_by {|s| [s[/[0-9a-z]+/], s.to_i]}
=> ["1", "10", "20", "abc", "Bar", "_def", "foo"]

3 个答案:

答案 0 :(得分:4)

您可以先创建组,然后对组进行排序。

arr.each_with_object(Array.new(3) { Array.new }) do |word, group|
  if word.match /^[A-Za-z]/
    group.first
  elsif word.match /^[0-9]/
    group.second
  else
    group.third
  end << word
end.flat_map{ |group| group.sort_by{ |x| x.downcase } }

#=> ["abc", "Bar", "foo", "1", "10", "20", "_def"]

答案 1 :(得分:3)

来自docs

以“元素方式”比较数组;使用ary运算符将other_ary的第一个元素与<=>的第一个元素进行比较,然后将每个第二个元素进行比较,等等……

您可以通过创建排序组来利用此行为:

arr = ["Bar", "abc", "foo", "1", "20", "10", "_def"]

arr.sort_by do |s|
  case s
  when /^[a-z]/i
    [1, s.downcase]
  when /^\d/
    [2, s.to_i]
  else
    [3, s]
  end
end
#=> ["abc", "Bar", "foo", "1", "10", "20", "_def"]

第一个元素(123)定义了组的位置:在第1个位置带有字母的字符串,在第2个位置带有数字字符串,其余的在第3个位置。在每个组中,元素按第二个元素排序:带字母的字符串按小写值排序,数字字符串按其整数值排序,其余按自身排序。

答案 2 :(得分:1)

需要一些基准:

require 'active_support/core_ext/array/access.rb'
require 'fruity'

ARR = ["Bar", "abc", "foo", "1", "20", "10", "_def"]

def run_demir(ary)
  ary.each_with_object(Array.new(3) { Array.new }) do |word, group|
    if word.match /^[A-Za-z]/
      group.first
    elsif word.match /^[0-9]/
      group.second
    else
      group.third
    end << word
  end.flat_map{ |group| group.sort_by{ |x| x.downcase } }
end

def run_stefan(ary)
  ary.sort_by do |s|
    case s
    when /^[a-z]/i
      [1, s.downcase]
    when /^\d/
      [2, s.to_i]
    else
      [3, s]
    end
  end
end

run_demir(ARR)  # => ["abc", "Bar", "foo", "1", "10", "20", "_def"]
run_stefan(ARR) # => ["abc", "Bar", "foo", "1", "10", "20", "_def"]

compare do
  demir  { run_demir(ARR)  }
  Stefan { run_stefan(ARR) }
end

这将导致:

# >> Running each test 512 times. Test will take about 1 second.
# >> Stefan is faster than demir by 2x ± 0.1