首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Elixir的深层递归

使用Elixir的深层递归
EN

Stack Overflow用户
提问于 2019-06-18 15:04:52
回答 2查看 198关注 0票数 1

我正在开发一个文件系统seaweedfs。我们已经将文件以适当的目录结构保存为server/camera_id/snapshots/recordings/year

我正在尝试删除年份下的空文件夹。

代码语言:javascript
复制
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"],要么给出[]

[]的情况下,我只是删除完整的树,如下所示

代码语言:javascript
复制
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中?任何帮助都是有帮助的,谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-19 14:59:05

这里有一种方法。将当前函数更改为使用已知的years调用recursive_delete

代码语言:javascript
复制
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)

然后:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2019-06-18 18:50:49

编辑:误解问题

因此,如果您想使用递归生成组合,我想您可以将参数(相机、服务器、年份)作为嵌套列表传递,并递归地构造组合(使用第一个列表(相机),并通过传递其余列表(服务器和年份)来构建列表。

这确实有一个优点,你可以传递任意数量的项目或列表,当你想在url中添加另一个级别时,它将构建组合,而不是添加一个更多级别的Enum.each

代码语言:javascript
复制
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)

这应该会生成如下内容

代码语言:javascript
复制
[
  ["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"]
]

您可以将它们分别连接成一个字符串

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56643464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档