Сортировка строк и чисел в Ruby

Я хочу сначала отсортировать массив по строкам, а затем по номерам. Как мне это сделать?

6 ответов


общий трюк для решения сложных сортировок-использовать #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. Сравнение определяется массив# способ:

массивы сравниваются "по элементам"; первый элемент ary сравнивается с первым элементом other_ary используя оператор, затем каждый из вторых элементов и т. д. ... Как только результат любого такого сравнения не равен нулю (т. е. два соответствующих элемента не равны), этот результат возвращается для сравнения всего массива.


сортировка массива смешанных чисел и строк, помещая числа сначала и в порядке, а затем строки второй, и в порядке.

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

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

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"] 

обычно алфавитизация выполняется сначала с числами. Если вы хотите что-то по алфавиту, где буквы по алфавиту до цифры, необходимо изменить использовать функцию сравнения.

# 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']

вот несколько подробных ответов. Разделите массив на два суб-массива: строки и числа, отсортируйте их и объедините.

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]

Если вы пытаетесь отсортировать смешанный случай и цифры, только несколько человек на Земле могут сделать это за пределами проприетарных приложений. Это секрет с ударом под дых. Вы должны использовать qsort, который упрощает сортировку, пока вы не смешиваете регистры (верхние и нижние буквы). Потом колледж, книги и интернет оставляют тебя в подвешенном состоянии. Этот хак стоит своего веса в золоте и является латунным кольцом программирования по всем причинам.

для сортировки чисел со словами вы должны преобразовать число в строку. Вы необходимо предварительно использовать верхний регистр. Если у вас есть слова "Муравей", "муравей" и "муравей" на меньше, они все должны указывать на слово "муравей" в верхнем регистре списка сортировки. Затем вы создадите список (массив) только из этих трех слов ["Ant", " ant " и " anT"] и используйте qsort в качестве выключателя для их сортировки.

затем вы вставляете их в окончательный массив сортировки. Это довольно сложно по дизайну. "A" - 65 на ascii, а " 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.

Это делает его проще, но, скорее всего, приведет к повышению производительности вне макросов большинства языков программирования. Удачи!