ElixirSchool 教程:深入理解 Elixir 集合类型

ElixirSchool 教程:深入理解 Elixir 集合类型

elixirschool The content behind Elixir School elixirschool 项目地址: https://gitcode.com/gh_mirrors/el/elixirschool

前言

在 Elixir 编程语言中,集合类型是构建程序的基础组件。本文将全面解析 Elixir 中的四种主要集合类型:列表(List)、元组(Tuple)、关键字列表(Keyword List)和映射(Map)。每种类型都有其独特的特点和适用场景,理解它们的差异对于编写高效、优雅的 Elixir 代码至关重要。

列表(List)

列表是 Elixir 中最基本的集合类型之一,它可以包含任意数量和类型的元素,甚至允许重复值。

基本特性

iex> [3.14, :pie, "Apple"]  # 包含浮点数、原子和字符串的列表
[3.14, :pie, "Apple"]

Elixir 中的列表实现为链表数据结构,这意味着:

  • 获取列表长度的时间复杂度是 O(n)
  • 在头部添加元素比在尾部添加效率更高

列表操作

头部插入 vs 尾部追加

# 头部插入(高效)
iex> ["π" | [3.14, :pie, "Apple"]]  
["π", 3.14, :pie, "Apple"]

# 尾部追加(效率较低)
iex> [3.14, :pie, "Apple"] ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]

列表连接与减法

Elixir 提供了 ++/2--/2 运算符分别用于列表连接和减法操作:

# 连接
iex> [1, 2] ++ [3, 4, 1]
[1, 2, 3, 4, 1]

# 减法(注意重复值的处理)
iex> [1,2,2,3,2,3] -- [1,2,3,2]
[2, 3]

头尾分解

处理列表时,经常需要访问其头部(第一个元素)和尾部(剩余部分):

iex> hd([3.14, :pie, "Apple"])  # 获取头部
3.14

iex> tl([3.14, :pie, "Apple"])  # 获取尾部
[:pie, "Apple"]

更优雅的方式是使用模式匹配:

iex> [head | tail] = [3.14, :pie, "Apple"]
iex> head
3.14
iex> tail
[:pie, "Apple"]

元组(Tuple)

元组与列表相似,但在内存中以连续方式存储,这使得:

  • 访问长度非常快速
  • 修改操作代价较高(需要完整复制)

基本用法

iex> {3.14, :pie, "Apple"}  # 使用花括号定义
{3.14, :pie, "Apple"}

元组常用于函数返回值,特别是需要返回状态和内容的情况:

# 文件读取成功
{:ok, "...文件内容..."}

# 文件读取失败
{:error, :enoent}  # enoent表示"不存在"的错误

关键字列表(Keyword List)

关键字列表是 Elixir 中的一种特殊列表,每个元素都是一个二元元组,且第一个元素必须是原子(atom)。

特点与语法

# 两种等效表示法
iex> [foo: "bar", hello: "world"]
iex> [{:foo, "bar"}, {:hello, "world"}]

关键字列表有三个重要特性:

  1. 键必须是原子
  2. 保持开发者定义的顺序
  3. 允许重复键

这些特性使其成为函数选项传递的理想选择。

映射(Map)

映射是 Elixir 中最常用的键值存储结构,相比关键字列表:

  • 键可以是任意类型
  • 不保持插入顺序

基本操作

# 创建映射
iex> map = %{:foo => "bar", "hello" => :world}

# 访问值
iex> map[:foo]
"bar"
iex> map["hello"]
:world

特殊语法

对于原子键,Elixir 提供了更简洁的语法:

# 简写形式
iex> %{foo: "bar", hello: "world"}

# 等效于
iex> %{:foo => "bar", :hello => "world"}

还可以使用点语法访问原子键的值:

iex> map.hello
"world"

更新映射

Elixir 提供了专门的更新语法(注意:这会创建新映射):

iex> %{map | foo: "baz"}  # 仅能更新已存在的键

要添加新键,需要使用 Map.put/3 函数:

iex> Map.put(%{hello: "world"}, :foo, "baz")
%{foo: "baz", hello: "world"}

总结对比

| 集合类型 | 语法示例 | 特点 | 典型用途 | |--------------|--------------------------|-----------------------------|-----------------------| | 列表 | [1, "two", :three] | 链表实现,头操作高效 | 顺序数据存储 | | 元组 | {:ok, result} | 连续内存,快速访问长度 | 函数返回值,固定结构 | | 关键字列表 | [key: "value"] | 键为原子,保持顺序,可重复键 | 函数选项传递 | | 映射 | %{key => value} | 任意键类型,无序,键唯一 | 通用键值存储 |

理解这些集合类型的特性和适用场景,将帮助你编写出更高效、更符合 Elixir 风格的代码。在实际开发中,根据具体需求选择合适的集合类型是提高代码质量的关键。

elixirschool The content behind Elixir School elixirschool 项目地址: https://gitcode.com/gh_mirrors/el/elixirschool

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕瑜旭Edwin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值