You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于子目录大小计算更新父目录大小(Elixir实现)

如何基于子目录大小计算更新父目录大小(Elixir实现)

嘿,我明白你现在的困境了——你已经拿到了每个目录的初始大小,想把所有子目录的大小累加进父目录里,但Elixir的不可变特性让你的代码没达到预期效果,对吧?先别着急,我们一步步来解决这个问题。

先分析你的问题根源

你原来的代码里尝试用递归和Enum.map更新父目录大小,但忽略了Elixir的核心特性:变量不可变。你在if块里写的system = system ++ [...]只是创建了一个局部的新变量,并没有把更新后的列表传递到递归调用里,最后自然返回了初始的空列表。而你用IO.inspect能看到中间结果,只是因为那个局部变量确实被创建了,但没有被保留下来而已。

解决方案思路

要实现需求,我们需要确保先处理最深的子目录,再处理父目录——这样当我们更新父目录大小时,所有子目录的大小已经被累加进去了。具体步骤是:

  1. 把目录列表按路径长度从长到短排序(比如先处理["/", "a", "e"],再处理["/", "a"],最后处理["/"])。
  2. 遍历每个目录,找到它的父目录(路径去掉最后一个元素),然后将当前目录的大小加到父目录的大小上。
  3. 利用Enum.reduce来累积更新后的目录列表,因为reduce天生适合这种需要逐步累积结果的场景。

具体代码实现

首先,写一个辅助函数来更新单个父目录的大小:

def update_parent_size(system, child_dir) do
  parent_path = List.delete_at(child_dir.path, -1)
  # 根目录没有父目录,直接返回原列表
  if parent_path == [] do
    system
  else
    Enum.map(system, fn dir ->
      if dir.path == parent_path do
        # 不可变更新:创建新的map,size加上子目录的大小
        %{dir | size: dir.size + child_dir.size}
      else
        dir
      end
    end)
  end
end

然后,主函数来协调整个更新流程:

def calculate_dir_sizes(initial_system) do
  # 按路径长度降序排序,确保先处理最深的子目录
  sorted_dirs = Enum.sort_by(initial_system, &length(&1.path), :desc)
  # 用reduce累积更新后的目录列表
  Enum.reduce(sorted_dirs, initial_system, fn dir, acc ->
    update_parent_size(acc, dir)
  end)
end

测试一下效果

用你给出的初始数据测试:

initial = [
  %{path: ["/", "a", "e"], size: 584},
  %{path: ["/", "a"], size: 94269},
  %{path: ["/", "d"], size: 24933642},
  %{path: ["/"], size: 23352670}
]

calculate_dir_sizes(initial)

返回的结果就是你想要的:

[
  %{path: ["/", "a", "e"], size: 584},
  %{path: ["/", "a"], size: 94853},
  %{path: ["/", "d"], size: 24933642},
  %{path: ["/"], size: 48381165}
]

额外小建议

你提到构建树结构可能更适合这个AoC挑战——确实,如果一开始就用树来存储目录结构,后续计算大小会更直观(比如递归遍历树,累加子节点的大小)。不过既然你已经走到这一步,上面的方法完全可以解决当前的问题。

备注:内容来源于stack exchange,提问作者shmink

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 07:05:30