#elixir
Вопрос:
Учитывая следующий список карт:
ball_prop_list =
[
%{"id" => "cue", "is_idle" => true, "velocity_x" => 0.0, "velocity_z" => 0.0, "x" => -15.0, "z" => 0.0},
%{"id" => "ball_1", "is_idle" => true, "velocity_x" => 0.0, "velocity_z" => 0.0, "x" => 15.0, "z" => 0.0},
%{"id" => "ball_2", "is_idle" => true, "velocity_x" => 0.0, "velocity_z" => 0.0, "x" => 17.0, "z" => 1.1},
%{"id" => "ball_3", "is_idle" => true, "velocity_x" => 0.0, "velocity_z" => 0.0, "x" => 17.0, "z" => -1.1}
]
Как мне просмотреть каждый элемент, а затем сравнить его с каждым элементом в списке (игнорируя сам себя)?
Исходный код написан на C# и, по сути, будет:
foreach (bodyA in objectList) {
foreach (bodyB in objectList) {
if (bodyA == bodyB) {
continue;
}
// Do other stuff here
}
}
Я попробовал это:
Enum.map(ball_prop_list , fn
body_a ->
Enum.map(ball_prop_list , fn body_b ->
if body_a["id"] != body_b["id"] do
Sys.Log.debug("#{body_a["id"]} (A) vs #{body_a["id"]} (B)")
# Compute other stuff here
end
end)
end)
Но я не думаю, что это работает так, как ожидалось, так как именно так выглядят журналы, неоднократно:
Я ожидал чего-то cue (A) vs ball_1 (B)
и т. Д., Но этого не произошло; и, конечно, это сравнение А с А, судя по всему. Есть ли что-нибудь еще, что я мог бы попробовать?
Комментарии:
1. Я думаю, вы могли бы упростить свой вопрос. Вы смотрели на понимание списка (и карты)? elixir-lang.org/getting-started/comprehensions.html Это рекомендуемый способ вычисления таких вещей, как декартовы произведения.
2. @Эверетт, спасибо, что в настоящее время я изучаю это, но, к сожалению, реальный ответ гораздо более неловок…
Ответ №1:
Буквальный перевод исходного кода был бы
Enum.each(ball_prop_list, fn body_a ->
Enum.each(ball_prop_list, fn
^body_a -> :ok
body_b -> # Do other stuff here
end)
end)
Ответ №2:
Как указывалось в другом месте, мой подход сработал бы; это была просто проблема с отображением:
Sys.Log.debug("#{body_a["id"]} (A) vs #{body_a["id"]} (B)")
Должно быть:
Sys.Log.debug("#{body_a["id"]} (A) vs #{body_b["id"]} (B)")
Хотя, как указал Эверетт в комментарии выше, рекомендуемым способом сделать это было бы использование понимания, которое выглядело бы примерно так:
for body_a <- ball_prop_list, # for clause 1, declares variable body_a
body_b <- ball_prop_list -- [body_a], # for clause 2, declares variable body_b
isCollisionDetected(body_a, body_b), do: # test clause, only true results pass
{:collision, a, b} # "Return statement": this is how we format passing results
Оператор return не совсем отформатирован так, как я бы хотел (все еще работаю над этим), поскольку это приведет к следующему:
[{:collision, obj5, obj99}, {:collision, obj1, obj7} ...]
# Where each obj is a map from ball_prop_list
но это еще одна проблема для другого времени, и это должно ответить на вопрос «что эквивалентно a для каждого внутри a для каждого».
Комментарии:
1. Хороший улов! Есть ли причина, по которой вы используете
Sys.Log.debug
вместоLogger.debug
этого ?2. @Everett, это не сказано в вопросе, но я использую собственную среду разработки серверов, которая просто использует Elixir для базы кода, и документация упомянутого SDE рекомендует нам использовать
Sys.Log.debug
. Я не пробовалLogger.debug
сам (или другие предложенныеIO.debug
, если я не ошибаюсь), но, к сожалению, я имею дело с людьми, которые предпочли бы, чтобы мы «придерживались документации», какой бы неполной или устаревшей она ни была.3.
for body_a <- ball_prop_list, body_b <- ball_prop_list -- [body_a]
это очень неправильный подход, потому что он повторяет список, чтобы удалить элемент, а затем выдает результат, а затем повторяет его снова. Правильным было быfor body_a <- ball_prop_list, body_b <- ball_prop_list, body_a != body_b
.4. @AlekseiMatiushkin, спасибо за уловку, я только что протестировал ее и, кажется, работает.