ruby alphanumeric sort not working as expected

前端 未结 4 937
盖世英雄少女心
盖世英雄少女心 2021-01-25 04:04

Given the following array:

y = %w[A1 A2 B5 B12 A6 A8 B10 B3 B4 B8]
=> [\"A1\", \"A2\", \"B5\", \"B12\", \"A6\", \"A8\", \"B10\", \"B3\", \"B4\", \"B8\"]
         


        
4条回答
  •  孤城傲影
    2021-01-25 04:40

    Here are a couple of ways to do that.

    arr = ["A1", "A2", "B5", "B12", "A6", "AB12", "A8", "B10", "B3", "B4",
           "B8", "AB2"]
    

    Sort on a 2-element array

    arr.sort_by { |s| [s[/\D+/], s[/\d+/].to_i] }
      #=> ["A1", "A2", "A6", "A8", "AB2", "AB12", "B3", "B4", "B5", "B8",
      #    "B10", "B12"] 
    

    This is similar to @Jorg's solution except I've computed the two elements of the comparison array separately, rather than splitting the string into two parts and converting the latter to an integer.

    Enumerable#sort_by compares each pair of elements of arr with the spaceship method, <=>. As the elements being compared are arrays, the method Array#<=> is used. See in particular the third paragraph of that doc.

    sort_by compares the following 2-element arrays:

    arr.each { |s| puts "%s-> [%s, %d]" %
      ["\"#{s}\"".ljust(7), "\"#{s[/\D+/]}\"".ljust(4), s[/\d+/].to_i] }
    
    "A1"   -> ["A" , 1]
    "A2"   -> ["A" , 2]
    "B5"   -> ["B" , 5]
    "B12"  -> ["B" , 12]
    "A6"   -> ["A" , 6]
    "AB12" -> ["AB", 12]
    "A8"   -> ["A" , 8]
    "B10"  -> ["B" , 10]
    "B3"   -> ["B" , 3]
    "B4"   -> ["B" , 4]
    "B8"   -> ["B" , 8]
    "AB2"  -> ["AB", 2]
    

    Insert spaces between the alphameric and numeric parts of the string

    max_len = arr.max_by(&:size).size
      #=> 4
    arr.sort_by { |s| "%s%s%d" % [s[/\D+/], " "*(max_len-s.size), s[/\d+/].to_i] }
      #=> ["A1", "A2", "A6", "A8", "AB2", "AB12", "B3", "B4", "B5", "B8",
      #    "B10", "B12"]
    

    Here sort_by compares the following strings:

    arr.each { |s| puts "%s-> \"%s\"" %
      ["\"#{s}\"".ljust(7), s[/\D+/] + " "*(max_len-s.size) + s[/\d+/]] }
    
    "A1"   -> "A  1"
    "A2"   -> "A  2"
    "B5"   -> "B  5"
    "B12"  -> "B 12"
    "A6"   -> "A  6"
    "AB12" -> "AB12"
    "A8"   -> "A  8"
    "B10"  -> "B 10"
    "B3"   -> "B  3"
    "B4"   -> "B  4"
    "B8,"  -> "B 8"
    "AB2"  -> "AB 2"
    

提交回复
热议问题