У меня есть рубиновый массив, который выглядит примерно так:
my_array = ['mushroom', 'beef', 'fish', 'chicken', 'tofu', 'lamb']
Я хочу отсортировать массив так, чтобы 'курица' и 'говядина' были первыми двумя объектами, затем остающиеся объекты отсортированы в алфавитном порядке. Как я пошел бы о выполнении этого?
irb> my_array.sort_by { |e| [ e == 'chicken' ? 0 : e == 'beef' ? 1 : 2, e ] }
#=> ["chicken", "beef", "fish", "lamb", "mushroom", "tofu"]
Это создаст ключ сортировки для каждого элемента массива, а затем отсортирует элементы массива по их ключам сортировки. Так как ключ сортировки является массивом, он сравнивается по позиции, поэтому [0, 'курица'] <[1, 'говядина'] <[2, 'яблоко'] <[2, 'банан']
.
Если вы не знаете, какие элементы вы хотите отсортировать до времени выполнения, вы все равно можете использовать этот трюк:
irb> promotables = [ 'chicken', 'beef' ]
#=> [ 'chicken', 'beef' ]
irb> my_array.sort_by { |e| [ promotables.index(e) || promotables.size, e ] }
#=> ["chicken", "beef", "fish", "lamb", "mushroom", "tofu"]
irb> promotables = [ 'tofu', 'mushroom' ]
#=> [ 'tofu', 'mushroom' ]
irb> my_array.sort_by { |e| [ promotables.index(e) || promotables.size, e ] }
#=> [ "tofu", "mushroom", "beef", "chicken", "fish", "lamb"]
Мой намного более универсален и более полезен, если вы получаете данные только во время выполнения.
my_array = ['mushroom', 'beef', 'fish', 'chicken', 'tofu', 'lamb']
starters = ['chicken', 'beef']
starters + (my_array.sort - starters)
# => ["chicken", "beef" "fish", "lamb", "mushroom", "tofu"]