Сортировка строк и чисел в рубине - PullRequest
5 голосов
/ 24 декабря 2009

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

Ответы [ 6 ]

17 голосов
/ 24 декабря 2009

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

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

>> a.partition{|x| x.is_a? String}.map(&:sort).flatten
=> ["a", "b", 1, 2]
15 голосов
/ 27 декабря 2009

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

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

3 голосов
/ 30 июля 2014
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"] 
2 голосов
/ 24 декабря 2009

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

# 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']
1 голос
/ 02 апреля 2010

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

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]
0 голосов
/ 27 декабря 2009

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

Чтобы отсортировать числа со словами, вы должны преобразовать числа в строку. Вы должны предварительно отсортировать в верхнем регистре. Если у вас меньше слов «Ant», «ant» и «anT», все они должны указывать на слово «ANT» в списке сортировки в верхнем регистре. Затем вы создадите список (массив) только из этих трех слов ["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 , М, М, Н, Н, ... 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 только для примера.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...