我正在开发一个文件系统seaweedfs。我们已经将文件以适当的目录结构保存为server/camera_id/snapshots/recordings/year
我正在尝试删除年份下的空文件夹。
def clean do
cameras =
Camera
|> preload(:owner)
|> order_by(desc: :created_at)
|> Evercam.Repo.all()
years = ["2015", "2016", "2017", "2018", "2019"]
servers = [@seaweedfs_new, @seaweedfs_old, @seaweedfs_oldest]
Enum.each(cameras, fn camera ->
Enum.each(servers, fn server ->
type = seaweefs_type(server)
attribute = seaweedfs_attribute(server)
url = server <> "/#{camera.exid}/snapshots/recordings/"
Enum.each(years, fn year ->
final_url = url <> year <> "/"
request_from_seaweedfs(final_url, type, attribute)
end)
end)
end)
end当最终请求在request_from_seaweedfs(final_url, type, attribute)中运行一年时
它要么给出一个这样的列表,["01", "02", "03"],要么给出[]
在[]的情况下,我只是删除完整的树,如下所示
url = server/gaol-yard/snapshots/recordings/2016/?recursive=true
hackney = [pool: :seaweedfs_download_pool, recv_timeout: 30_000]
HTTPoison.delete!("#{url}?recursive=true", [], hackney: hackney)但我想要更深入地了解,如果结果不是[],那么我想进入几个月,例如
months = ["01", "02", "03"]
final_url = url <> year <> "/" <> "{moth value from the list}"
对于每个月,有连续的几天,然后有几天有小时,
我想用递归检查所有这些,比如如果最后一层或任何一层是空的,就删除一棵树,
例如,如果相机有年、月、日和小时,但在最后一个级别中,如果小时给了[],则删除整个树。
这可以用Enum.each来实现,每次如果我没有得到[],就再循环一遍,直到最后一层,它说[]删除了它,但是可以通过更程序化的方式吗?在递归中而不是这么多的eachs中?任何帮助都是有帮助的,谢谢
发布于 2019-06-19 14:59:05
这里有一种方法。将当前函数更改为使用已知的years调用recursive_delete
Enum.each(cameras, fn camera ->
Enum.each(servers, fn server ->
type = seaweefs_type(server)
attribute = seaweedfs_attribute(server)
url = server <> "/#{camera.exid}/snapshots/recordings/"
recursive_delete(years, url, type, attribute)
end)
end)然后:
def recursive_delete([], _, _, _), do: :done
def recursive_delete(entries, url, type, attribute) do
Enum.each(entries, fn entry ->
entry_url = url <> entry <> "/"
entry_url
|> request_from_seaweedfs(type, attribute)
|> recursive_delete(entry_url, type, attribute)
end)
end发布于 2019-06-18 18:50:49
编辑:误解问题
因此,如果您想使用递归生成组合,我想您可以将参数(相机、服务器、年份)作为嵌套列表传递,并递归地构造组合(使用第一个列表(相机),并通过传递其余列表(服务器和年份)来构建列表。
这确实有一个优点,你可以传递任意数量的项目或列表,当你想在url中添加另一个级别时,它将构建组合,而不是添加一个更多级别的Enum.each。
defmodule Test do
def perm(input, acc \\ [])
def perm([], acc), do: acc
def perm([first_arr | rest_arr], acc) do
first_arr
|> Enum.map(fn val ->
perm(rest_arr, [val | acc])
end)
end
def flat([fst | rst]) when is_list(fst) do
case fst do
[fst1 | _rst1] when is_list(fst1) -> flat(fst ++ rst)
_ -> [fst] ++ flat(rst)
end
end
def flat(other), do: other
end
cameras = ["gaol-yard", "gaol-yard-1", "gaol-yard-2"]
years = ["2015", "2016", "2017", "2018", "2019"]
servers = ["seaweedfs_new", "seaweedfs_old", "seaweedfs_oldest"]
# input = [[1,2,3], [:a,:b,:c], [5.0, 6.0, 7.0]]
[cameras, years, servers] \
|> Test.perm() \
|> Test.flat \
|> Enum.map(&Enum.reverse/1)这应该会生成如下内容
[
["gaol-yard", "2015", "seaweedfs_new"],
["gaol-yard", "2015", "seaweedfs_old"],
["gaol-yard", "2015", "seaweedfs_oldest"],
["gaol-yard", "2016", "seaweedfs_new"],
["gaol-yard", "2016", "seaweedfs_old"],
["gaol-yard", "2016", "seaweedfs_oldest"],
...
"gaol-yard-1", "2015", "seaweedfs_old"],
["gaol-yard-1", "2015", "seaweedfs_oldest"],
["gaol-yard-1", "2016", "seaweedfs_new"],
...
["gaol-yard-2", "2019", "seaweedfs_new"],
["gaol-yard-2", "2019", "seaweedfs_old"],
["gaol-yard-2", "2019", "seaweedfs_oldest"]
]您可以将它们分别连接成一个字符串
https://stackoverflow.com/questions/56643464
复制相似问题