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_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 回答
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 回答