如何从较小的多边形中创建较大的多边形

时间:2018-04-19 11:40:32

标签: functional-programming elixir

我想转换以下多边形列表:

[
  %{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遍中获得所有多边形?

2 个答案:

答案 0 :(得分:1)

我在这里使用Enum.reduceEnum.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轴连接。这个例子很有趣,因为地图实例不常用作累加器。