0

次のような地域の郵便番号のソートされていないリストがあります。

["E1", "E1C", "E1D", "E10", "E11", "E12", "E2", "E3", "E4", "EC1", "EC1A", "EC1M", "EC1N",
"EC1R", "EC1V", "EC1Y", "EC2", "EC2A", "EC2M", "EC2N", "N1", "N10", "N11", "N12",
"N13", "N2", "NW1", "NW10", "NW2" etc]

以下のように並べ替えたいと思います。

["E1", "E1C", "E1D", "E2", "E3", "E4", "E10", "E11", "E12", "EC1", "EC1A", "EC1M", "EC1N",
"EC1R", "EC1V", "EC1Y", "EC2", "EC2A", "EC2M", "EC2N", "N1", "N2", "N10", "N11", "N12",
"N13", "NW1", "NW2, "NW10" etc]

したがって、E で始まる郵便番号の形式の順序をまとめると、次のようになります。

  • E1
  • E1C
  • E11
  • EC1
  • EC1V

N で始まる郵便番号の順序などは同じです。

そのような文字列をソートするための推奨される方法は何ですか? この場合、文字列の形式は常に既知です。つまり、常に 2 ~ 4 文字の英数字で、最初の文字は常に文字です。

最初に文字列を長さで注文してから、各長さのグループ内で注文する必要がありますか、それともより洗練された方法がありますか?

4

2 に答える 2

0

ちょっと変わったやり方ですが、これでうまくいくと思います:

array.sort do |a, b|
  a = a.dup
  b = b.dup

  regex = /(\d+)/
  a.match(regex)
  a_num = $1.to_i
  b.match(regex)
  b_num = $1.to_i

  if a_num > b_num
    a.gsub!(regex, "1")
    b.gsub!(regex, "0")
  elsif a_num < b_num
    a.gsub!(regex, "0")
    b.gsub!(regex, "1")
  end

  a <=> b
end
于 2012-10-03T00:23:58.467 に答える
0

私は使うだろう

array.sort_by do |str|
  /\A(\w)(\d+)\Z/ === str
  [$1, $2.to_i]
end

または、任意の文字と数字の交互のシーケンスがある場合は、

array.sort_by do |str|
  /\A(\D*)(\d*)(\D*)(\d*)\Z/.match(str)[1..-1].reject(&:blank?).collect do |item|
    /\d/ === item ? item.to_i : item
  end
end
于 2012-10-02T23:49:28.240 に答える