Пользовательский Сортировать массив строк по другому массиву строк - Ruby - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть массив, который в настоящее время сортируется по алфавиту, и я пытаюсь отсортировать его по порядку строк вручную.

Текущий код:

list = ["gold","silver","bronze","steel","copper"]

list = list.sort { |a, b| a <=> b }

Что япытаюсь добиться: (с пустой записью в качестве разделителя)

list = ["gold","silver","bronze","steel","copper"]

sort_order = ["bronze","silver","gold","","copper","steel"]

list = list.sort_by sort_order

Вывод: бронза |серебро |золото |- |медь |сталь

Возможно ли это?В настоящее время застрял с этими сообщениями об ошибках:

comparison of Integer with nil failed
comparison of String with String failed

Ответы [ 2 ]

2 голосов
/ 09 апреля 2019

Я предполагаю, что:

  • каждый элемент list находится в sort_order;
  • sort_order может содержать элементы, которых нет в list;
  • list может содержать дубликаты; и
  • sort_order не содержит дубликатов.

Если sort_order изначально содержит дубликаты, временный массив sort_order.uniq может использоваться в расчетах.

Заметьте, что если, как в примере, list не содержит дубликатов и sort_order не содержит элементов, отличных от элементов в list, сортировка list по порядку элементов в sort_order тривиальна, так как он просто возвращает sort_order.

Следующее более эффективно, чем методы, использующие вычислительную сложность sort или sort_by (O(n) против O(n*log(n)).)

list = ["gold", "copper", "silver", "copper", "steel", "gold"]
sort_order = ["bronze", "silver", "tin", "gold", "copper", "steel"]

count = list.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
  #=> {"gold"=>2, "copper"=>2, "silver"=>1, "steel"=>1} 
sort_order.flat_map { |e| [e]*count[e] }.reject(&:empty?)
  #=> ["silver", "gold", "gold", "copper", "copper", "steel"] 
1 голос
/ 09 апреля 2019

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

class Medal
  attr_accessor :name, :rank

  def initialize(name, rank)
    @name = name
    @rank = rank
  end
end

list = [Medal.new("gold", 0), Medal.new("silver", 1), Medal.new("bronze", 2), Medal.new("steel", 4), Medal.new("copper", 3)]

list = list.sort_by &:rank

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

Но если вы не хотите этого делать, то, возможно, у вас также может быть просто список.порядка и сортировки по индексу, вот так

list = ["gold","silver","bronze","steel","copper"]

sort_order = ["bronze","silver","gold","","copper","steel"]

list = list.sort_by {|m| sort_order.index m}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...