给定以下地图列表:
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)
等,但它没有发生;当然,从事物的外观来看,它是将 A 与 A 进行比较。还有什么我可以尝试的吗?
答案 0 :(得分: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)
答案 1 :(得分:0)
正如其他地方所指出的,我的方法会奏效;这只是一个显示问题:
Sys.Log.debug("#{body_a["id"]} (A) vs #{body_a["id"]} (B)")
应该是:
Sys.Log.debug("#{body_a["id"]} (A) vs #{body_b["id"]} (B)")
尽管正如 Everett 在上面的评论中指出的那样,推荐的这样做的方法是使用理解,它看起来像这样:
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 for each 中的 a for each 的等价物是什么”的问题。