Есть ли для Ruby метод natural_sort_by? - PullRequest
15 голосов
/ 02 ноября 2010

У меня есть список файлов с кучей атрибутов.Одним из атрибутов является имя файла, как я хотел бы отсортировать список.Тем не менее, список выглядит примерно так: имя файла 1, имя файла 2, имя файла 10, имя файла 20.

Метод ruby ​​sort_by дает следующее:

files = files.sort_by { |file| file.name }
=> [filename 1, filename 10, filename 2, filename 20]

Я бы хотел, чтобы человек читалсясписок, такой как имя файла 1, имя файла 2, имя файла 10, имя файла 20

Я нашел камень natural_sort , но, похоже, он работает только как метод сортировки.Мне нужно что-то, где я могу указать, что сортировать массив по.

Любая помощь?

Ответы [ 6 ]

24 голосов
/ 02 ноября 2010

Вот еще один пример «естественного» метода сортировки:

class String
  def naturalized
    scan(/[^\d\.]+|[\d\.]+/).collect { |f| f.match(/\d+(\.\d+)?/) ? f.to_f : f }
  end
end

Это преобразует что-то вроде "Filename 10" в простой массив с плавающей точкой вместо чисел [ "Filename", 10.0 ]

Youможете использовать это в своем списке:

files.sort_by! { |file| file.name.to_s.naturalized }

Это имеет преимущество работы с произвольными числами в непредсказуемых позициях.Параноидальный вызов .to_s в этом блоке должен гарантировать, что при сортировке есть строка, а не случайный nil.

13 голосов
/ 02 марта 2013

универсальный ответ для строк естественной сортировки

array.sort_by {|e| e.split(/(\d+)/).map {|a| a =~ /\d+/ ? a.to_i : a }}
7 голосов
/ 04 января 2013

Я создал камень натуральной сортировки .Он может сортировать по атрибуту, как это:

# Sort an array of objects by the 'number' attribute
Thing = Struct.new(:number, :name)
objects = [
  Thing.new('1.1', 'color'),
  Thing.new('1.2', 'size'),
  Thing.new('1.1.1', 'opacity'),
  Thing.new('1.1.2', 'lightness'),
  Thing.new('1.10', 'hardness'),
  Thing.new('2.1', 'weight'),
  Thing.new('1.3', 'shape')
  ]
Naturally.sort_by(objects, :number)

# => [#<struct Thing number="1.1", name="color">,
      #<struct Thing number="1.1.1", name="opacity">,
      #<struct Thing number="1.1.2", name="lightness">,
      #<struct Thing number="1.2", name="size">,
      #<struct Thing number="1.3", name="shape">,
      #<struct Thing number="1.10", name="hardness">,
      #<struct Thing number="2.1", name="weight">]
6 голосов
/ 02 ноября 2010

Пока файлы всегда называются "file #", вы можете сделать

files.sort_by{|f| f.name.split(" ")[1].to_i }

Это разделяет пробел и захватывает номер для сортировки.

0 голосов
/ 01 января 2019

natural_sort камень .

Установка

gem "natural_sort"

Использование

list = ["a10", "a", "a20", "a1b", "a1a", "a2", "a0", "a1"]
list.sort(&NaturalSort) # => ["a", "a0", "a1", "a1a", "a1b", "a2", "a10", "a20"]
0 голосов
/ 04 января 2013

сортируется правильно.Проблема здесь в том, что имена не подходят для сортировки так, как вы хотите.В виде строки, 10 предшествует 2, а 21 предшествует 5.

Если вы хотите, чтобы оно сортировалось так, как оно было в числах, у вас есть 2 подхода:

1 - изменить все ваши спискидобавить перед нулями перед 0 цифры только с одной цифрой.

2 - Сделайте, как предложил Уильям, введите имя, преобразуйте строку в целое и отсортируйте по ней.

Я бы порекомендовал вариант 1поскольку вторые полагаются на падронизацию имен.

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