热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关键字列表有什么好处?

如何解决《关键字列表有什么好处?》经验,为你挑选了2个好方法。

在灵丹妙药中我们有地图:

> map = %{:a => "one", :b => "two"} # = %{a: "one", b: "two"}
> map.a                             # = "one"
> map[:a]                           # = "one"

我们还有关键字列表:

> kl = [a: "one", b: "two"]       # = [a: "one", b: "two"]
> kl2 = [{:a, "one"},{:b, "two"}] # = [a: "one", b: "two"]
> kl == kl2                       # = true
> kl[:a]                          # = "one"
> kl.a                            # = ** (ArgumentError)

两个为什么?

句法?是因为关键字列表具有更灵活的语法,允许它们被定义为没有卷曲,甚至没有括号作为函数调用的最后一个参数?那为什么不给这个语法糖吗?

重复密钥?是因为关键字列表可以有重复的键吗?为什么要同时使用Map样式访问和重复键?

性能?是因为关键字列表有更好的表现吗?那为什么要有地图?并且不应该通过键查找成员比使用元组列表更高效吗?

JS Array和Ruby Hash一样外观?是吗?

我理解结构上它们是不同的数据表示.对我而言,似乎elixir中的关键字列表通过特殊语法(3种不同的句法变体),用例与地图重叠以及不明确的好处使语言复杂化.

使用关键字列表有什么好处?



1> Patrick Osci..:
                   ?????????????????????????????????????????????????????
                   ? Keyword List ? Map/Struct ? HashDict (deprecated) ?
????????????????????????????????????????????????????????????????????????
? Duplicate keys   ? yes          ? no         ? no                    ?
? Ordered          ? yes          ? no         ? no                    ?
? Pattern matching ? yes          ? yes        ? no                    ?
? Performance¹     ? —            ? —          ? —                     ?
? ? Insert         ? very fast²   ? fast³      ? fast?                 ?
? ? Access         ? slow?        ? fast³      ? fast?                 ?
????????????????????????????????????????????????????????????????????????

关键字列表是轻量级的,在它们下面有一个简单的结构,这使它们非常灵活.您可以将它们视为基于Erlang约定的语法糖,使得在不编写过于丑陋的代码的情况下轻松与Erlang进行交互.例如,关键字列表用于表示函数参数,这是从Erlang继承的属性.在某些情况下,关键字列表是您唯一的选择,特别是如果您需要重复键或订购.它们具有与其他替代品不同的特性,这使得它们更适合某些情况而不适合其他情况.

Maps(和Structs)用于存储实际的有效负载数据,因为它们具有基于散列的实现.内部的关键字列表只是每个操作需要遍历的列表,因此它们不具有经典键值数据结构的属性,如常量时间访问.

Elixir还介绍HashDict了在编写地图时地图表现不佳的解决方法.但是,现在从Elixir 1.0.5/Erlang 18.0开始修复HashDict ,将来的版本将不推荐使用.

如果深入研究Erlang标准库,还有更多存储键/值对的数据结构:

proplists - 类似于Elixir关键字列表

地图 - 与Elixir地图相同

dict - 从Erlang原语构建的键值字典

gb_trees - 一般平衡树

当您需要跨多个进程和/或VM存储键/值对时,您还可以使用以下选项:

ets/dets - (基于磁盘)Erlang术语存储

mnesia - 分布式数据库


¹一般来说,但当然取决于 ™.

²最好的情况只是在列表前面.

³适用于Elixir 1.0.5及更高版本,在旧版本中可能会更慢.

HashDict现在被弃用了.

⁵需要线性搜索,平均扫描一半的元素.


@greggreg使用关键字列表还有另一个隐含的好处:我们对结构化和非结构化数据进行区分.地图对于具有已知密钥集的结构化数据非常有用,而关键字则不是.今天,大多数地图用于结构化数据,我们为可选数据留下关键字.如果我们只有地图,我认为这种区别的很大一部分将会丢失.
严格来说,是的,但如果您需要这些属性,它们可能会带来好处 - 这就是我的意思.

2> Voldy..:

关键字列表的主要好处是与现有的elixir和erlang代码库向后兼容.

如果用作函数参数,它们也会添加语法糖,类似于ruby语法:

def some_fun(arg, opts \\ []), do: ...
some_fun arg, opt1: 1, opt2: 2

使用关键字列表的主要缺点是无法对它们执行部分模式匹配:

iex(1)> m = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(2)> %{a: a} = m
%{a: 1, b: 2}
iex(3)> a
1
iex(4)> k = [a: 1, b: 2]
[a: 1, b: 2]
iex(5)> [a: a] = k
** (MatchError) no match of right hand side value: [a: 1, b: 2]

让我们将它扩展为函数参数.想象一下,我们需要根据其中一个选项的值来处理多重函数:

def fun1(arg, opt1: opt1) when is_nil(opt1), do: do_special_thing
def fun1(arg, opts), do: do_regular_thing

def fun2(arg, %{opt1: opt1}) when is_nil(opt1), do: do_special_thing
def fun2(arg, opts), do: do_regular_thing

这永远不会执行do_special_thing:

fun1("arg", opt1: nil, opt2: "some value")
doing regular thing  

使用map参数,它将起作用:

fun2("arg", %{opt1: nil, opt2: "some value"})
doing special thing


推荐阅读
author-avatar
许心怡917
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有