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