首页 理论教育 使用Elixir实现列表转换

使用Elixir实现列表转换

时间:2023-11-20 理论教育 版权反馈
【摘要】:列表转换涉及重复操作,可以用递归函数来完成。让我们看看如何使用递归函数来构建一个转换列表。埃德温是一位巫师,他经营着一家销售魔法物品的商店。创建一个名为EnchanterShop的模块存放到文件enchanter_shop.ex里。它也是遍历列表的终止条件。最后一个表达式用[head | tail]语法构建新列表,列表的第一个元素是刚转换的新物品,列表的其余部分是对nchant_for_sale的递归调用。现在普通长剑变成了有魔法的埃德温长剑。

使用Elixir实现列表转换

我们经常遇到需要做列表转换的情况,比如将借记帐户转换成冻结帐户、将博客草稿转换成发布的帖子、将字符串转换成其他数据结构、将用户输入内容转换成表格的行。数据在函数式编程中是不可变的,因此转换数据实际上需要创建新的数据。列表转换涉及重复操作,可以用递归函数来完成。让我们看看如何用递归构建新列表。

[head | tail]语法不但可以用来解构参数,也能用来构建新列表。在IEx中尝试以下代码,看看它是如何工作的:

表达式 [:a | [:b,:c]]和[:a,:b | [:c]]的结果是相同的,都是列表[:a,:b,:c]。我们可以用这种方式构建新列表,每次增加一个元素。注意:这种构建方式将元素逐个添加到列表中,它比使用++运算符追加元素快许多倍。让我们看看如何使用递归函数来构建一个转换列表。

这是一个魔法世界的例子。埃德温是一位巫师,他经营着一家销售魔法物品的商店。他的工作是施法将普通物品变成魔法物品,并提高售价。每件经他施法的物品都会标上他的名字。魔法物品售价是原来的三倍。让我们为埃德温构建一个转换模块。创建一个名为EnchanterShop的模块存放到文件enchanter_shop.ex里。首先,我们创建一个包含测试数据的函数,以了解它的结构:

所有物品都是用映射表表示的。其中包含物品的名称和价格,还有一个标志,说明该物品是否已施法。现在我们要创建遍历此列表并进行转换的代码。让我们创建一个enchant_for_sale函数:

第一个函数子句的作用是,当物品列表为空时,返回一个空的待售物品列表。它也是遍历列表的终止条件。第二个子句负责进行递归转换。它使用模式匹配提取第一个物品,然后将它转换成新的魔法物品。物品的名称现在要加上巫师的名字,价格变成原来的三倍,同时把施法标志设为真。最后一个表达式用[head | tail]语法构建新列表,列表的第一个元素是刚转换的新物品,列表的其余部分是对nchant_for_sale的递归调用。

基于键的访问器

Elixir允许用[]语法借助键访问关键字列表和映射表中的值。如果键不存在,则返回nil值,这是不会引发错误。(www.xing528.com)

对结构体和映射表,可以使用点表示法访问原子键的值。如果键不存在,则会引发错误。

对此感兴趣的读者可以查阅Elixir的官方文档。[1]

让我们看看它的工作情况:

我们完成了转换。现在普通长剑变成了有魔法的埃德温长剑。稍等,原来列表中的一些物品本来就是有魔法的。我们不能对有魔法物品再次施法。让我们添加一行代码,确保有魔法的物品不会被再次施法。我们把新子句放在边界条件子句和转换子句之间:

在新子句中,我们用映射表模式匹配来检查物品是否已有魔法。方法是检查参数是否包含子集%{magic:true}。如果匹配,我们将映射表参数绑定到变量item,不做任何转换,直接用它构建新列表。

再次编译,并查看效果:

这一次,原来有魔法的物品保留了它们的原始属性。现在,我们已经掌握了如何转换列表,以及如何使用函数子句来跳过不必要的转换。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈