在Ruby中对字符串和数字进行排序

时间:2009-12-23 22:22:42

标签: ruby sorting

我想首先按字符串对数组进行排序,然后是数字。我该怎么做?

6 个答案:

答案 0 :(得分:17)

对数字和字符串数组进行排序,先将数字放在第一位,按顺序排在第二位,然后按顺序排列。

>> a = [1, 2, "b", "a"]

>> a.partition{|x| x.is_a? String}.map(&:sort).flatten
=> ["a", "b", 1, 2]

答案 1 :(得分:15)

解决棘手排序的一般技巧是使用#sort_by,该块返回一个具有主要和次要排序顺序的数组(如果需要,还有三级等)

a = ['foo', 'bar', '1', '2', '10']  
b = a.sort_by do |s|
  if s =~ /^\d+$/
    [2, $&.to_i]
  else
    [1, s]
  end
end
p b    # => ["bar", "foo", "1", "2", "10"]

这是有效的,因为Ruby定义了数组比较的方式。比较由Array#<=>方法定义:

  

阵列以“元素方式”进行比较;使用&lt; =&gt;将ary的第一个元素与other_ary的第一个元素进行比较。运算符,然后是每个第二个元素等等......只要任何这样的比较结果不为零(即两个相应的元素不相等),就会返回整个数组比较的结果。

答案 2 :(得分:3)

a = ['1', '10', '100', '2', '42', 'hello', 'x1', 'x20', 'x100', '42x', '42y', '10.1.2', '10.10.2', '10.8.2']
a.map {|i| i.gsub(/\d+/) {|s| "%08d" % s.to_i } }.zip(a).sort.map{|x,y| y}
# => ["1", "2", "10", "10.1.2", "10.8.2", "10.10.2", "42", "42x", "42y", "100", "hello", "x1", "x20", "x100"] 

答案 3 :(得分:2)

通常,首先使用数字进行字母化。如果你想按字母顺序排列字母在数字前按字母顺序排列的东西,你需要改变使用的比较函数。

# I realize this function could be done with less if-then-else logic,
# but I thought this would be clearer for teaching purposes.
def String.mysort(other)
  length = (self.length < other.length) ? self.length : other.length
  0.upto(length-1) do |i|
    # normally we would just return the result of self[i] <=> other[i]. But
    # you need a custom sorting function.
    if self[i] == other[i]
      continue # characters the same, skip to next character.
    else
      if self[i] ~= /[0-9]/
        if other[i] ~= /[0-9]/
          return self[i] <=> other[i]  # both numeric, sort normally.
        else
          return 1  # self is numeric, other is not, so self is sorted after.
        end
      elsif other[i] ~= /[0-9]/
        return  -1  # self is not numeric, other is, so self is sorted before.
      else
        return self[i] <=> other[i]    # both non-numeric, sort normally.
      end
    end
  end

  # if we got this far, the segments were identical. However, they may
  # not be the same length. Short sorted before long.
  return self.length <=> other.length
end

['0','b','1','a'].sort{|x,y| x.mysort(y) } # => ['a', 'b', '0', '1']

答案 4 :(得分:1)

这是一个有点冗长的答案。将数组划分为两个子数组:字符串和数字,对它们进行排序并连接它们。

array = [1, 'b', 'a', 'c', 'd', 2, 4, 3]
strings = []
numbers = []
array.each do |element|
  if element.is_a? String
    strings << element
  else
    numbers << element
  end
end
sorted_array = strings.sort + numbers.sort
sorted_array # ['a', 'b', 'c', 'd', 1, 2, 3, 4]

答案 5 :(得分:0)

如果您尝试对混合案例和数字进行排序,那么地球上只有少数人可以在专有应用程序之外执行此操作。这是一个傻逼的秘密。您必须使用qsort,这样可以轻松排序,直到混合大小写(大写和小写字母)。然后大学,书籍和互联网让你垂头丧气。这个黑客非常重视黄金,并且出于各种原因是编程的铜环。

要使用单词对数字进行排序,必须将数字转换为字符串。你必须使用大写预先分配。如果你有更少的单词“Ant”,“ant”和“anT”,他们都应该指向大写排序列表中的单词“ANT”。然后,您将创建一个仅包含这三个单词[“Ant”,“ant”和“anT”]的列表(数组) 并使用qsort作为打破平局来对它们进行排序。

然后将它们插入到最终的排序数组中。设计相当困难。 “A”在ascii上是65,“a”是97,在'Z'和'a'之间有很多垃圾字符!这不是偶然的!这是我告诉你的阴谋!

您可以创建一个排序表,对字符进行更合理的分组:

A,a,B,b,C,c,D,d,E,e,F,f,G,g,H,h,I,i,J,j,K,k,L,l ,M,m,N,n,...... 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 ......

围绕此块构建表,以“”(空格)ascii 32到128开始。您可能希望按顺序重新排序A 65中的数字。

这使得它更容易,但可能会导致性能损失超出大多数编程语言的宏。祝好运!