Эликсир: Что эквивалентно а для каждого в пределах а для каждого?

#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, спасибо за уловку, я только что протестировал ее и, кажется, работает.