Elixir列表 #
一、列表基础 #
1.1 列表定义 #
列表是元素的有序集合,可以包含任意类型的元素:
elixir
iex(1)> [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
iex(2)> ["hello", "world"]
["hello", "world"]
iex(3)> [1, "two", :three, 4.0]
[1, "two", :three, 4.0]
iex(4)> []
[]
1.2 列表特性 #
列表是链表结构,头部访问O(1),随机访问O(n):
elixir
iex(1)> list = [1, 2, 3]
[1, 2, 3]
iex(2)> hd(list)
1
iex(3)> tl(list)
[2, 3]
iex(4)> length(list)
3
1.3 列表与字符列表 #
elixir
iex(1)> [1, 2, 3]
[1, 2, 3]
iex(2)> [104, 101, 108, 108, 111]
'hello'
二、列表操作 #
2.1 拼接 #
elixir
iex(1)> [1, 2] ++ [3, 4]
[1, 2, 3, 4]
iex(2)> [1, 2, 3] ++ [4, 5]
[1, 2, 3, 4, 5]
2.2 差集 #
elixir
iex(1)> [1, 2, 3, 2, 1] -- [2, 1]
[1, 3, 2]
iex(2)> [:a, :b, :c, :d] -- [:b, :d]
[:a, :c]
2.3 成员检查 #
elixir
iex(1)> 1 in [1, 2, 3]
true
iex(2)> 4 in [1, 2, 3]
false
iex(3)> :a in [:a, :b, :c]
true
2.4 头尾操作 #
elixir
iex(1)> list = [1, 2, 3]
[1, 2, 3]
iex(2)> hd(list)
1
iex(3)> tl(list)
[2, 3]
iex(4)> List.first(list)
1
iex(5)> List.last(list)
3
2.5 插入元素 #
elixir
iex(1)> list = [2, 3]
[2, 3]
iex(2)> [1 | list]
[1, 2, 3]
iex(3)> List.insert_at([1, 3, 4], 1, 2)
[1, 2, 3, 4]
2.6 删除元素 #
elixir
iex(1)> List.delete([1, 2, 3, 2], 2)
[1, 3, 2]
iex(2)> List.delete_at([1, 2, 3], 1)
[1, 3]
iex(3)> List.first([1, 2, 3])
1
iex(4)> List.last([1, 2, 3])
3
2.7 替换元素 #
elixir
iex(1)> List.replace_at([1, 2, 3], 1, :two)
[1, :two, 3]
iex(2)> List.update_at([1, 2, 3], 1, fn x -> x * 2 end)
[1, 4, 3]
2.8 列表反转 #
elixir
iex(1)> Enum.reverse([1, 2, 3])
[3, 2, 1]
三、模式匹配 #
3.1 头尾匹配 #
elixir
iex(1)> [head | tail] = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
iex(2)> head
1
iex(3)> tail
[2, 3, 4, 5]
3.2 多元素匹配 #
elixir
iex(1)> [a, b, c | rest] = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
iex(2)> a
1
iex(3)> b
2
iex(4)> c
3
iex(5)> rest
[4, 5]
3.3 空列表匹配 #
elixir
iex(1)> [] = []
[]
iex(2)> case [] do
...> [] -> "Empty"
...> [head | tail] -> "Has elements"
...> end
"Empty"
四、递归处理 #
4.1 基本递归 #
elixir
defmodule MyList do
def sum([]), do: 0
def sum([head | tail]), do: head + sum(tail)
def length([]), do: 0
def length([_ | tail]), do: 1 + length(tail)
def product([]), do: 1
def product([head | tail]), do: head * product(tail)
end
4.2 尾递归优化 #
elixir
defmodule MyList do
def sum(list), do: sum(list, 0)
defp sum([], acc), do: acc
defp sum([head | tail], acc), do: sum(tail, acc + head)
def reverse(list), do: reverse(list, [])
defp reverse([], acc), do: acc
defp reverse([head | tail], acc), do: reverse(tail, [head | acc])
def map([], _func), do: []
def map([head | tail], func), do: [func.(head) | map(tail, func)]
end
4.3 递归示例 #
elixir
defmodule MyList do
def filter([], _pred), do: []
def filter([head | tail], pred) do
if pred.(head) do
[head | filter(tail, pred)]
else
filter(tail, pred)
end
end
def reduce([], acc, _func), do: acc
def reduce([head | tail], acc, func) do
reduce(tail, func.(head, acc), func)
end
def flatten([]), do: []
def flatten([head | tail]) when is_list(head) do
flatten(head) ++ flatten(tail)
end
def flatten([head | tail]) do
[head | flatten(tail)]
end
end
五、Enum模块 #
5.1 遍历 #
elixir
iex(1)> Enum.each([1, 2, 3], fn x -> IO.puts(x) end)
1
2
3
:ok
iex(2)> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
iex(3)> Enum.each_with_index(["a", "b", "c"], fn {item, index} ->
...> IO.puts("#{index}: #{item}")
...> end)
0: a
1: b
2: c
:ok
5.2 过滤 #
elixir
iex(1)> Enum.filter([1, 2, 3, 4, 5], fn x -> x > 2 end)
[3, 4, 5]
iex(2)> Enum.reject([1, 2, 3, 4, 5], fn x -> x > 2 end)
[1, 2]
iex(3)> Enum.take([1, 2, 3, 4, 5], 3)
[1, 2, 3]
iex(4)> Enum.drop([1, 2, 3, 4, 5], 2)
[3, 4, 5]
iex(5)> Enum.take_while([1, 2, 3, 4, 5], fn x -> x < 4 end)
[1, 2, 3]
iex(6)> Enum.drop_while([1, 2, 3, 4, 5], fn x -> x < 4 end)
[4, 5]
5.3 查找 #
elixir
iex(1)> Enum.find([1, 2, 3, 4, 5], fn x -> x > 3 end)
4
iex(2)> Enum.find_value([1, 2, 3, 4, 5], fn x -> if x > 3, do: x * 2 end)
8
iex(3)> Enum.find_index([1, 2, 3, 4, 5], fn x -> x > 3 end)
3
iex(4)> Enum.member?([1, 2, 3], 2)
true
5.4 聚合 #
elixir
iex(1)> Enum.reduce([1, 2, 3, 4, 5], 0, fn x, acc -> acc + x end)
15
iex(2)> Enum.reduce([1, 2, 3, 4, 5], fn x, acc -> acc + x end)
15
iex(3)> Enum.sum([1, 2, 3, 4, 5])
15
iex(4)> Enum.product([1, 2, 3, 4, 5])
120
iex(5)> Enum.min([3, 1, 4, 1, 5, 9])
1
iex(6)> Enum.max([3, 1, 4, 1, 5, 9])
9
iex(7)> Enum.min_max([3, 1, 4, 1, 5, 9])
{1, 9}
5.5 排序 #
elixir
iex(1)> Enum.sort([3, 1, 4, 1, 5, 9])
[1, 1, 3, 4, 5, 9]
iex(2)> Enum.sort([3, 1, 4, 1, 5, 9], :desc)
[9, 5, 4, 3, 1, 1]
iex(3)> Enum.sort_by(["banana", "apple", "cherry"], &String.length/1)
["apple", "banana", "cherry"]
iex(4)> Enum.uniq([1, 2, 1, 3, 2, 4])
[1, 2, 3, 4]
5.6 分组 #
elixir
iex(1)> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]
iex(2)> Enum.chunk_every([1, 2, 3, 4, 5], 2, 1)
[[1, 2], [2, 3], [3, 4], [4, 5]]
iex(3)> Enum.split([1, 2, 3, 4, 5], 3)
{[1, 2, 3], [4, 5]}
iex(4)> Enum.split_with([1, 2, 3, 4, 5], fn x -> x > 2 end)
{[3, 4, 5], [1, 2]}
iex(5)> Enum.group_by(["apple", "banana", "apricot"], fn x -> String.first(x) end)
%{"a" => ["apple", "apricot"], "b" => ["banana"]}
5.7 连接 #
elixir
iex(1)> Enum.join([1, 2, 3], "-")
"1-2-3"
iex(2)> Enum.join(["a", "b", "c"])
"abc"
iex(3)> Enum.concat([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]
iex(4)> Enum.concat([[1, 2], [3, 4], [5, 6]])
[1, 2, 3, 4, 5, 6]
5.8 转换 #
elixir
iex(1)> Enum.into([1, 2, 3], [])
[1, 2, 3]
iex(2)> Enum.into([{:a, 1}, {:b, 2}], %{})
%{a: 1, b: 2}
iex(3)> Enum.to_list(1..3)
[1, 2, 3]
六、管道操作符 #
6.1 基本用法 #
elixir
iex(1)> [1, 2, 3, 4, 5]
...> |> Enum.filter(fn x -> x > 2 end)
...> |> Enum.map(fn x -> x * 2 end)
...> |> Enum.sum()
24
6.2 链式处理 #
elixir
def process_data(data) do
data
|> Enum.filter(&valid?/1)
|> Enum.map(&transform/1)
|> Enum.sort()
|> Enum.take(10)
end
七、列表推导式 #
7.1 基本语法 #
elixir
iex(1)> for x <- [1, 2, 3], do: x * 2
[2, 4, 6]
iex(2)> for x <- [1, 2, 3], y <- [4, 5, 6], do: x * y
[4, 5, 6, 8, 10, 12, 12, 15, 18]
7.2 过滤 #
elixir
iex(1)> for x <- 1..10, x > 5, do: x
[6, 7, 8, 9, 10]
iex(2)> for x <- 1..10, rem(x, 2) == 0, do: x
[2, 4, 6, 8, 10]
7.3 解构 #
elixir
iex(1)> users = [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}]
[%{age: 30, name: "Alice"}, %{age: 25, name: "Bob"}]
iex(2)> for %{name: name} <- users, do: name
["Alice", "Bob"]
7.4 转换结果类型 #
elixir
iex(1)> for x <- 1..5, into: [], do: x * 2
[2, 4, 6, 8, 10]
iex(2)> for x <- 1..5, into: %{}, do: {x, x * 2}
%{1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10}
iex(3)> for x <- 1..5, into: "", do: <<x + 96>>
"abcde"
八、性能考虑 #
8.1 列表 vs 元组 #
| 操作 | 列表 | 元组 |
|---|---|---|
| 头部插入 | O(1) | O(n) |
| 随机访问 | O(n) | O(1) |
| 长度计算 | O(n) | O(1) |
8.2 避免的操作 #
elixir
list ++ [element]
list -- [element]
length(list)
Enum.at(list, index)
8.3 推荐的操作 #
elixir
[element | list]
[element | list]
使用元组存储固定大小数据
使用映射存储键值对
九、总结 #
本章学习了:
| 操作 | 示例 |
|---|---|
| 创建 | [1, 2, 3] |
| 拼接 | [1, 2] ++ [3, 4] |
| 头尾 | [head | tail] |
| 遍历 | Enum.each/2, Enum.map/2 |
| 过滤 | Enum.filter/2 |
| 聚合 | Enum.reduce/3 |
| 推导式 | for x <- list, do: x |
准备好学习元组了吗?让我们进入下一章。
最后更新:2026-03-27