Help us understand the problem. What is going on with this article?

Elixir: リストとタプルはいつどちらを使うのか

More than 1 year has passed since last update.

リストもタプルも、ともに複数のデータの容れ物です。値の型は問わず、いくつでも要素として納められます(「Elixir入門 02: 型の基本」参照)。

iex> list = [3.14, :pie, true, "Apple"]
[3.14, :pie, true, "Apple"]
iex> tuple = {3.14, :pie, true, "Apple"}
{3.14, :pie, true, "Apple"}

けれど、ふたつの仕組みは異なり、したがって使い途も変わります。ふたつの違いとしては、つぎのような点が挙げられます。

違い タプル リスト
サイズ 固定 可変
要素の操作 原則としてしない ListのほかEnumの関数が使える
データの参照 速い 遅くなることがある

リストの仕組み

リストは「連結リスト」です。要素は値とつぎの要素への参照をもちます。要素を特定するインデックスは備えません。

qiita_12_001_001.png

タプルの仕組み

タプルは、連番インデックスをもった静的なデータ構造です。インデックス順に、まとめてメモリに納められます。

qiita_12_001_002.png

サイズに関わる違い

リストは要素を加えたり、除いたりすることが自由です。その数とそれぞれのデータによって、リストのサイズは変わります。タプルは、要素をまとめて納めたときに、サイズが決まります。要素の追加や削除は、実際上行われません。

サイズを得る関数は、リストがlength/1、タプルはtuple_size/1です。つぎのような処理の違いがあります。

関数 値の求め方 処理
length/1 数えて返す 遅い
tuple_size/1 あらかじめ計算されている 速い

要素の追加や削除などの操作

リストはListのほかEnumモジュールの豊富な関数で操作できます。特定の要素を追加したり、削除したり、変更するだけでなく、すべての要素を取り出して処理できるのです。

タプルを操作するTupleモジュールの関数は多くありません。要素を操作したいときには、リストを使うことが推奨されています。要素を加えたり、書き替えたりする場合は、メモリに新たなタプルをつくることになるので、負荷が高くなってしまうからです。

To manipulate a collection of elements, use a list instead.
(「Tuple」より)

データの参照と取り出し

リストにはインデックスがなく、要素間の参照をたどることで値が取り出されます。つまり、最後の要素を参照するには、すべての要素を順にたどらなければならないということです。もっとも、すべての要素を列挙して処理するには差し支えなく、Enumモジュールの関数が使えます。

タプルの要素は、elem/2関数により、インデックスを与えてただちに取り出せます。ただし、Enumモジュールの関数は使えません。

iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> elem(tuple, 1)
"hello"

適した使い途

リストは、要素を自由に操作でき、メモリの許すかぎり加えられます。タプルは、予め決まったデータのやり取りに向くでしょう。

データを操作したり、数が変わったり、とくに多くの数のデータを扱うにはリストが使われます。1件のデータの複数の属性値を表すときは、タプルが適しているでしょう。典型は、キーと値の組みです。関数の戻り値によく用いられます。たとえば、File.read/1は、ファイル読み込みの結果と内容をタプルで返します。

iex> File.read("path/to/existing/file")
{:ok, "... ファイルの中身 ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}

また、タプルはパターンマッチングにも用いられます。

iex> tuple = {:ok, :example}
{:ok, :example}
iex> {:ok, atom} = tuple
{:ok, :example}
iex> atom
:example

属性の数が増えてくると、タプルよりマップの方がわかりやすいかもしれません。

iex> {100, 150, 50}
{100, 150, 50}
iex> %{x: 100, y: 150, z: 50}
%{x: 100, y: 150, z: 50}

リストとタプルを組み合わせることもできます。キーワードリストがまさにその例です(「Elixir入門 07: キーワードリストとマップ」参照)。

iex> point = [x: 100, y: 150, z: 50]
[x: 100, y: 150, z: 50]
iex> point == [{:x, 100}, {:y, 150}, {:z, 50}]
true

まとめ

  • リストもタプルも任意の型のデータを複数納められます。
  • リストとタプルの仕組みは異なるので、つぎの点で違いがあります。
    • サイズ
    • 要素の操作
    • データの参照
  • リストとタプルそれぞれの性質にあった使い途があります。
    • リスト: 要素を操作し、数が変わるデータ
    • タプル: 複数の属性をもった固定データ
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away