列表与元组 - 使用什么以及何时使用?

时间:2015-07-02 19:21:13

标签: elixir

我正在努力理解Elixir列表元组之间的区别。从Elixir指南的Basic Types部分,我理解:

  • 列表存储为已链接的项目
  • 更新列表很快(仅在预先添加时)
  • 提取列表项目很慢
  • 获取列表信息(大小/长度)很慢
  • 元组元素存储在一起
  • 快速获取元组信息
  • 快速提取元组元素
  • 修改元组很贵

好的,这一切都很好但我还不确定时要使用什么。我看到大多数方法返回一个元组但是其他地方都使用了Lists,并且许多方法接受Lists作为输入,而不是元组。根据上面提到的观点,不应该使用元组来传递数据,因为从用户给定值的元组读取会很快吗?

我也注意到元组不是可枚举的,那是什么?不会在{1}上使用Enum比在列表中使用它更快吗?

如果有人可以帮助我更好地理解它们,可能只是举几个例子说明什么时候使用,那就太棒了。

6 个答案:

答案 0 :(得分:36)

你已经对这些差异给出了很好的总结,所以在其中一件事情很重要的任何条件下,它都应该帮助你决定使用哪些。

考虑它的方法是列表是开放式数据结构,它们的大小可以在运行时变化,而元组在编译时设置了恒定的大小。

例如,如果您想要存储用户在iex会话期间提供的所有命令,您需要一个列表 - 该列表的长度将取决于该会话中给出的命令数。将其与元组的典型用例进行对比 - 从方法中返回{:ok, result}{:error, reason} - 此处元素的数量是预先知道的,因此您不会为性能付出不可接受的代价元组的改进。

至于枚举 - 元组概念上不是集合,每个元素的位置也应该表示它的作用。考虑一个{:ok, #PID<0.336.0>}元组 - 迭代它会首先给你一个:ok然后一个#PID<0.336.0>,编写一个以统一的方式对这些东西起作用的函数会很奇怪。 / p>

答案 1 :(得分:18)

我不是专家,但这是我的理解:

在幕后,列表是一个链表。因此它具有链表的性能特征。也就是说,获取长度是O(n)因为我必须遍历整个列表。同样,列表也具有链表的优点;也就是说,通过添加到前面来增加它很容易。

我不确定幕后是什么元组,但我知道它不是一个链表。有人问到2013年在Elixir语言邮件列表上列举了元组,这是回复的一部分:

  

“元组也不应该被迭代,不要被混淆   事实上你可以使用elem / 2和size / 1。元组是为了   将多条信息存储在一起,这并不意味着   它们用于存储集合。“

- Peter Minten

  

“另一种解释是,元组是穷人的记录   换句话说,元组代表单个数据,单个数据   价值,虽然是汇总。你不能从元组中夺走一个元素   而不改变该特定元组值的语义含义。

     

“这与存储许多内容的列表和其他集合相反   重视独立价值观。简单地从列表中取出一个值   减少列表的长度。它不会影响语义   任何东西。“

- Alexei Sholik

换句话说,仅仅因为元组和列表之间存在肤浅的相似性,就不应该假设行为是相同的。

答案 2 :(得分:12)

除了已经说过的内容之外,帮助我区分元组和列表的内容类似于数据库中的一行。如果你以这种方式考虑元组,很容易看出元组中的信息是如何相互关联的,并且很明显为什么你不会将它用作Enumerable。

答案 3 :(得分:1)

如果您熟悉Java:

  • 列表类似于LinkedList
  • 元组就像ArrayList

答案 4 :(得分:0)

由于有人提到他们不确定元组在引擎盖下是什么类型,因此元组与数组类似,因为数组和元组都将元素存储在连续的内存中。因此,当您在链接列表上使用数组时,将遵循相同的规则,就像使用Elixir中的列表上的元组一样。

答案 5 :(得分:0)

Tuples旨在容纳固定数量的元素,这就是为什么它们预先分配内存的原因。基本上,元组不是要更改的(尽管有可能,但代价昂贵)。它们提供了一条相关信息。

例如:地理坐标{43.258389,-2.924405}

相反,列表更适合动态集合(修改起来更便宜)。

我发现这篇文章非常有用:https://blog.appsignal.com/2018/08/21/elixir-alchemy-list-vs-tuples.html