我想转换以下多边形列表:
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
进入相邻多边形连接的列表,如下所示:
[
%{height: 32, width: 96, x: 0, y: 0},
%{height: 32, width: 64, x: 256, y: 0}
]
我尝试过如下使用Enum.reduce_while:
Enum.reduce_while(polys, 0, fn poly, max_x ->
if poly.x - max_x <= 32, do: {:cont, max_x + 32}, else: {:halt, max_x}
end)
这可以给我第一个多边形,但是如何获得后续多边形,是否可以在1遍中获得所有多边形?
答案 0 :(得分:1)
我在这里使用Enum.reduce
。 Enum.reduce_while
适用于您希望根据某些条件进一步停止处理列表的情况。在这种情况下,您确实希望处理整个列表。
我所做的是从累加器中收集多边形,从仅包含第一个多边形的列表开始。然后,在每次缩小中,我检查前一个多边形x
+ width
是否与新多边形x
相同。如果是,我通过添加宽度来合并多边形,如果不是,我会在前面添加多边形。
反过来收集列表,因此我在减少后使用Enum.reverse
。
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
|> Enum.reduce(nil, fn
x, nil ->
[x]
x, [h | t] ->
if h.x + h.width == x.x do
[%{h | width: x.width + h.width} | t]
else
[x, h | t]
end
end)
|> Enum.reverse()
|> IO.inspect()
输出:
[%{height: 32, width: 96, x: 0, y: 0}, %{height: 32, width: 64, x: 256, y: 0}]
答案 1 :(得分:1)
这对于Enum.chunk_while/4
来说是一个完美的用例:
input = [
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
chunk_fun = fn
i, [] -> {:cont, i}
%{width: iw, x: ix}, %{height: ah, width: aw, x: ax, y: ay}
when ax + aw == ix ->
{:cont, %{height: ah, width: aw + iw, x: ax, y: ay}}
%{height: ih, y: iy}, %{height: ah, width: aw, x: ax, y: ay}
when ay + ah == iy ->
{:cont, %{height: ah + ih, width: aw, x: ax, y: ay}}
i, acc -> {:cont, acc, i}
end
after_fun = fn
[] -> {:cont, []}
acc -> {:cont, acc, []}
end
input
|> Enum.chunk_while([], chunk_fun, after_fun)
|> IO.inspect()
#⇒ [%{height: 32, width: 96, x: 0, y: 0},
# %{height: 32, width: 64, x: 256, y: 0}]
请注意,上面的示例也处理y轴连接。这个例子很有趣,因为地图实例不常用作累加器。