elixir - 迭代 Elixir 中的嵌套列表
问题描述
我试图解决这个问题很长一段时间,只有我发现的解决方案真的很难看。必须有更好的方法来解决这个问题:
给定配置
iterations = 2
tasklist = [
{:system, print: "sth"},
{:system, loop: [
{:device1, run: "cmd" },
{:device2, run: "cmd" },
], iterations: 3},
{:device3, run: "cmd" },
]
配置正在从上到下进行处理,每个命令都会打印一些结果(输出到 CSV 文件),除了{:system, loop: []}
. 命令定义不同,可以包括范围作为输入值。
我想创建一个函数,允许我通过将此配置扩展到新的步骤列表来实现嵌套循环,而无需循环和迭代,但将这些信息保留在每个步骤中。因此,如果步骤的输入值为范围,则软件能够从步骤中提取总迭代次数和当前迭代次数,并使用它来进行一些其他计算。
所以基本上是一个将原始配置转换为这个的函数:
tasklist = [
{:system, print: "sth",mainiteration: 1, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 1, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 1, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 1, maintotalit: 2},
{:system, print: "sth",mainiteration: 1, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 2, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 2, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 1, maintotalit: 2},
{:system, print: "sth",mainiteration: 1, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 3, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 3, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 1, maintotalit: 2},
{:system, print: "sth",mainiteration: 2, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 1, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 1, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 2, maintotalit: 2},
{:system, print: "sth",mainiteration: 2, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 2, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 2, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 2, maintotalit: 2},
{:system, print: "sth",mainiteration: 2, maintotalit: 2},
{:device1, run: "cmd" ,loopiteration: 3, looptotalit: 3},
{:device2, run: "cmd" ,loopiteration: 3, looptotalit: 3},
{:device3, run: "cmd" ,mainiteration: 2, maintotalit: 2},
]
通过配置步骤的当前代码是:
Enum.each(1..iterations, fn n ->
Enum.each(tasklist, fn task ->
IO.inspect(task) # My custom implementation
end)
end)
解决方案
欢迎来到堆栈溢出!
对于初学者来说,elixir是一种不可变的函数式语言,因此您可能熟悉的基于oop的常见“循环”概念在这里并不适用。但当然,您仍然可以以其他方式迭代数据集合,包括、each/2
和推导 式。map/2
reduce/4
如果您只是想打印每个项目的结果或在迭代中触发一次性事件而不返回任何内容,each/2
这是最简单的选择,否则您最好使用map/2
orreduce/3
解决您的实际问题,您可以通过使用函数子句中的模式匹配和递归处理模块中任务列表的每个场景来实现:
defmodule TaskList do
def handle({:system, print: message}) do
IO.puts(message)
end
def handle({:system, loop: tasks, iterations: count}) do
Enum.each(1..count, fn _ ->
Enum.each(tasks, &handle/1)
end)
end
def handle({device, run: command}) do
# Call your command on the device
# (Replace with your own implementation)
end
def handle(unknown) do
# Do nothing or handle unexpected situations here
end
def process_all(tasks, iterations) when is_list(tasks) do
handle({:system, loop: tasks, iterations: iterations})
end
end
根据您想要的输出方式进行一些小的更改后,您可以这样调用它:
TaskList.process_all(my_tasks, 2)
推荐阅读
- flutter - sliverAppBar 的圆底
- node.js - 如何使用 docker 容器在两个不同的端口上启动同一个 docker 容器?
- python - 如何检查一列的每个值是否映射到另一列中的一个值?
- data-structures - 如何防止 Nil 将容器恢复为其默认值?
- axios - 对话流代码未将数据发布到 Google 电子表格。Firebox 中没有记录错误
- javascript - 执行特定功能后加载脚本
- mysql - 未找到 Laravel 基表或视图:1146 表
- python - Keras 层中使用的自定义函数如何获取其参数?
- c - 用于打印人员基本信息的结构中的数组
- python-3.x - 在 RHEL6 上安装 pandas 时出现 SSL 模块问题