Вот еще один многословный способ сделать это:
order = [:col1, :col2, :col3]
cols = [:col3, :col2, :col5, :col4]
sorted_order = cols.sort_by do |c|
if order.index(c)
[1, order.index(c)]
else
[2, cols.index(c)]
end
end
p sorted_order # => [:col2, :col3, :col5, :col4]
Вот как это работает. sort_by возвращает элементы массива в блок; блок должен затем возвращать что-то сопоставимое (технически то, что отвечает оператору <=>). sort_by использует оператор <=> для результатов, возвращаемых блоком, чтобы решить, в каком порядке должен быть массив.
Оператор <=> (космический корабль), как вы, возможно, знаете, является двоичным оператором, принимающим два элемента a и b. Если a b, возвращается + 1.
Массивы не удивительно отвечают оператору <=>. Элементы левого массива сравниваются с элементами правого массива по очереди, начиная с индекса 0 и увеличиваясь. Если a [i] <=> b [i] равно! = 0, верните этот результат, но если результат равен 0, проверьте следующий элемент. Если последняя пара сравниваемых элементов равна 0 (равно), а массивы имеют одинаковый размер, массивы равны, и Array. <=> Возвращает 0, в противном случае более длинный массив считается большим (однако в этом примере всегда возвращаются массивы одинакового размера, однако ).
Так, например:
[2, 1] <=> [2, 2] == -1
[2, 2] <=> [2, 2] == 0
[2, 3] <=> [2, 2] == +1
[1, 2] <=> [2, 1] == +1
Итак, внутри sort_by мы можем использовать элементы массива a для указания первичного, вторичного, третичного и т. Д. Порядка сортировки. [0] - это первичный порядок сортировки, a [1] - это вторичный порядок сортировки и т. д.
Все столбцы, указанные клиентом, должны стоять на первом месте. Поэтому для каждого столбца найдите его индекс в указанном заказчиком порядке (order
). Если это возвращает число, то мы знаем, что клиент указал этот столбец, и мы знаем его индекс в указанном клиентом списке. Основной порядок сортировки - 1, потому что мы хотим, чтобы указанные пользователем столбцы были первыми; вторичный порядок сортировки - это индекс, поскольку он дает нам заказ, указанный клиентом в столбцах.
Если мы не найдем столбец в массиве order (то есть, order.index (c) возвращает nil), тогда мы будем использовать 2 в качестве основного порядка сортировки и индекс в списке главного столбца (cols
) как вторичный порядок сортировки. Таким образом, все столбцы, которые клиент не указал, будут последними, но в порядке, указанном в списке последних столбцов.