#arrays #ruby-on-rails #ruby #hash
Вопрос:
У меня есть массив, как показано ниже:
product = [[{:pm=>61, :scs=>20, :focus=>8}, {:pm=>61, :scs=>23, :focus=>8}],
[{:pm=>65, :scs=>20, :focus=>8}, {:pm=>65, :scs=>23, :focus=>8}],
[{:pm=>59, :scs=>20, :focus=>1}, {:pm=>59, :scs=>23, :focus=>1}],
[{:pm=>60, :scs=>20, :focus=>1}, {:pm=>60, :scs=>23, :focus=>1}],
[{:pm=>70, :scs=>20, :focus=>10}, {:pm=>70, :scs=>25, :focus=>10}],
[{:pm=>85, :scs=>60, :focus=>10}, {:pm=>85, :scs=>25, :focus=>10}],
[{:pm=>72, :scs=>20, :focus=>10}, {:pm=>72, :scs=>25, :focus=>10}]]
В одном месте мне нужно показать приведенный выше список в определенном порядке,этот порядок создается на основе взаимодействия с пользователем, то есть «group_pm_list», и задается в виде хэша,за которым нужно следовать, чтобы упорядочить приведенный выше массив:
group_pm_list={"8"=>[65,61],"1"=>[60,59],"10"=>[70,85,72]}
Здесь нам нужно переупорядочить «продукт» на основе «group_pm_list» (который представляет собой упорядоченный список продуктов на основе некоторой фильтрации).
Сначала мне нужно получить ключ 8(:фокус) со значениями » pm » 65, затем 61. Во-вторых, мне нужно получить ключ 1(:фокус) со значениями » pm » 60, затем 59. В-третьих, мне нужно получить ключ 10(:фокус), и в этой группе необходимо поддерживать тот же порядок.
Как я могу сгенерировать отсортированный список, как указано в приведенном выше порядке group_pm_list, чтобы получить результат в виде:
product = [[{:pm=>65, :scs=>20, :focus=>8}, {:pm=>65, :scs=>23, :focus=>8}],
[{:pm=>61, :scs=>20, :focus=>8},{:pm=>61,:scs=>23, :focus=>8}],
[{:pm=>60, :scs=>20, :focus=>1},{:pm=>60, :scs=>23, :focus=>1}],
[{:pm=>59, :scs=>20, :focus=>1}, {:pm=>59, :scs=>23, :focus=>1}],
[{:pm=>70, :scs=>20, :focus=>10}, {:pm=>70, :scs=>25, :focus=>10}],
[{:pm=>85, :scs=>60, :focus=>10}, {:pm=>85, :scs=>25, :focus=>10}],
[{:pm=>72, :scs=>20, :focus=>10}, {:pm=>72, :scs=>25, :focus=>10}]]
Пожалуйста, помогите.Спасибо
Комментарии:
1. Я не уверен, почему эти данные представляют собой массив массивов? Самое первое , что вы с ним делаете, — это вызов
.flatten
, который подразумевает, что предыдущая операция возвращает неправильно отформатированную структуру данных.
Ответ №1:
Это очень запутанный способ определения порядка сортировки:
group_pm_list={"8"=>[65,61],"1"=>[60,59]}
- Почему ключи являются строками, а не числами? Я предполагаю, что вы на самом деле хотели указать цифры и будете предполагать это в остальной части этого ответа.
- Вы уверены, что это не просто «сортировать по
:pm
убыванию»?? Это значительно более сложный порядок сортировки… - Не могли бы вы определить порядок сортировки с помощью более чистого объекта данных? В этом хэше нет никакого упоминания о
:focus
nor:pm
, поэтому немного странно «волшебным образом» знать, что это значит.
Я также предположу, что вы сгладите массив в какой-то момент, прежде чем использовать этот ответ, поскольку нет смысла, чтобы ваши данные были массивом массивов. Возможно, просто позвоните product.flatten!
наверх, если изменение переменной нормально?
product = [{:pm=>61, :scs=>20, :bg=>"#a3ffff", :impact=>4, :focus=>8}, {:pm=>61, :scs=>23, :bg=>"#a3ffff", :impact=>nil, :focus=>8}, {:pm=>65, :scs=>20, :bg=>"#a3ffff", :impact=>nil, :focus=>8}, {:pm=>65, :scs=>23, :bg=>"#a3ffff", :impact=>nil, :focus=>8}, {:pm=>59, :scs=>20, :bg=>"#ffffd9", :impact=>nil, :focus=>1}, {:pm=>59, :scs=>23, :bg=>"#ffffd9", :impact=>4, :focus=>1}, {:pm=>60, :scs=>20, :bg=>"#ffffd9", :impact=>1, :focus=>1}, {:pm=>60, :scs=>23, :bg=>"#ffffd9", :impact=>1, :focus=>1}]
group_pm_list={8 => [65,61], 1 =>[60,59]}
focus_sort_order = group_pm_list.keys
pm_sort_order = group_pm_list.values.flatten
product.sort do |p1, p2|
[
focus_sort_order.index(p1[:focus]),
pm_sort_order.index(p1[:pm])
] <=>
[
focus_sort_order.index(p2[:focus]),
pm_sort_order.index(p2[:pm])
]
end
Комментарии:
1. Ошибка типа (без неявного преобразования символа в целое число) из focus_sort_order.index(p1[:фокус]),
2. @джисси, Правда? Я просто скопировал вставил код на свою машину снова, чтобы запустить его, и не увидел ошибки. Возможно, вы все еще используете массив массивов, не выравнивая его сначала, как я предупреждал.
3. Если вам интересно, как работает эта реализация, см.: rubydoc.info/stdlib/core/Array:sort и ruby-doc.org/core-2.7.0/Array.html#method-i-3C-3D-3E . Реализация, по общему признанию, довольно сложна для понимания, но это неизбежно, учитывая очень странную/пользовательскую логику, которую вы пытаетесь применить здесь.
Ответ №2:
product = [
[{:pm=>61, :scs=>20, :focus=>8}, {:pm=>61, :scs=>23, :focus=>8}],
[{:pm=>65, :scs=>20, :focus=>8}, {:pm=>65, :scs=>23, :focus=>8}],
[{:pm=>59, :scs=>20, :focus=>1}, {:pm=>59, :scs=>23, :focus=>1}],
[{:pm=>60, :scs=>20, :focus=>1}, {:pm=>60, :scs=>23, :focus=>1}],
[{:pm=>70, :scs=>20, :focus=>10}, {:pm=>70, :scs=>25, :focus=>10}],
[{:pm=>85, :scs=>60, :focus=>10}, {:pm=>85, :scs=>25, :focus=>10}],
[{:pm=>72, :scs=>20, :focus=>10}, {:pm=>72, :scs=>25, :focus=>10}]
]
group_pm_list={"8"=>[65,61],"1"=>[60,59],"10"=>[70,85,72]}
Сол 1
group_pm_list.flat_map do |k, v|
v.flat_map do |m|
product.select { |n|
n[0][:pm] == m
}
end
end
Сол 2
grouped_products = product.group_by {|elem| elem[0][:pm]}
group_pm_list.flat_map do |k, v|
v.flat_map { |m| grouped_products[m] }
end
Сол 3
grouped_products = product.group_by {|elem| elem[0][:pm]}
group_pm_list.flat_map do |k, v|
v.map { |m| grouped_products[m][0] }
end
Комментарии:
1. Жесткое кодирование
"8"
не кажется разумным решением. Вы не можете предположить, что определенное число , например8
, находится в порядке сортировки.2. @TomLord, который может исходить из запроса, имеет вопрос, укажите, есть ли
:focus
номер, который будет там, поэтому я просто закодировал его3. Хорошо, но это невозможно доказать никаким реальным решением в реальном мире. Вот почему я сказал, что это не совсем правильный ответ.