Map! 数据类型

1. 概要

映射(map)代表一个内含键值对的关联数组,它提供了快速的读取访问(内部使用散列表)和便捷的专用语法。不像 hash! 数据类型,映射不是一个序列,所以它不存在偏移量和位置的概念。从概念上来说,map! 是一种处于 hash!object! 之间的数据类型。

2. 字面语法

#(<key> <value>...)

<key>   : 散列键,接受的类型为:scalar! , all-word! , any-string!
<value> : any-type! 值

3. 创建语法

make map! <spec>

<spec> : 内含键值对的区块或整数值

如果 spec 参数是整数,则会创建一个含有预分配数目槽位(通常用于动态地填充该映射)的空 map!

注意
  • map 的主体区块,或者说 spec 区块必须包含偶数个元素,否则将会生成一个错误。

  • 值不会被 reduce,所以某些特殊的值需要使用构造语法,比如 logic!

例:

#(a: 1 b: 2)
== #(
    a: 1
    b: 2
)

make map! [a 1 'b 2 "c" 3]
== #(
    a: 1
    b: 2
    "c" 3
)

如果键是 any-word! 类型,映射中的键的类型会被转换为 set-word!,这是为了使映射的内容看起来更像一组设置了值的键。不过,要访问单词键并不需要提供设词,出于实践性的考虑,你可以使用朴素的单词。类型的,keys-of 反射器(在下面的反射小节有描述)不会返回设词而会返回单词,因为这能简化之后的处理(尤其对于匹配操作,用单词比用设词简单)。

注意
  • hash!block! 那样,map! 默认是大小写保留查找时大小写不敏感的。

  • 如果指定 none 作为值,那么相应的键不会被创建(参照 “删除键” 小节)。

  • 在创建映射时,所有的键都会被深度拷贝。

  • 在创建映射时,series! 值不会被拷贝,这个选择是留给用户的(这优化了常见用例的资源占用)。

另一种创建新的映射的方式是对现存的映射调用 copy 动作。

4. 检索值

使用路径:

<map>/<key>
get '<map>/<key>

<map> : 引用 map! 值的单词
<key> : 单词键

使用挑选动作:

select <map> <key>

<map> : 映射值
<key> : 任何有效的键类型

所有这些读取访问都是大小写不敏感的,如果使用区分大小写的查找,需要在可用的地方用上 /case 修饰词:

get/case '<map>/<key>
select/case <map> <key>

尝试访问映射中不存在的键会返回 none 值。

例:

m: #(Ab: 2 aB: 5 ab: 10)
m/ab
== 2
select m 'aB
== 2
get/case 'm/aB
== 5
select/case m 'ab
== 10

5. 修改键和值

使用路径:

<map>/<key>: <value>
set '<map>/<key> <value>

<map>   : 引用 map! 值的单词
<key>   : 用于在映射中挑选值的单词键
<value> : 任意值

使用更改动作:

put <map> <key> <value>

<map> : 映射值
<key> : 任何用于在映射中挑选值的有效的键

做批量修改:

extend <map> <spec>

<map>  : 映射值
<spec> : 内含名称值对的区块(一对或多对)

所有这些读取访问都是大小写不敏感的,如果使用区分大小写的查找,需要在可用的地方用上 /case 修饰词:

set/case '<map>/<key> <value>
put/case <map> <key> <value>
extend/case <map> <spec>

extend 原生可以一次性接收许多键,所以用于批量修改很方便。

注意
  • 设置一个映射中之前不存在的键仅会简单地创建它

  • 添加一个现存的键会改变该键的值,并不会添加一个新的键(默认以大小写不敏感的方式匹配)。

例:

m: #(Ab: 2 aB: 5 ab: 10)
m/ab: 3
m
== #(
    Ab: 3
    aB: 5
    ab: 10
)

put m 'aB "hello"
m
== #(
    Ab: "hello"
    aB: 5
    ab: 10
)

set/case 'm/aB 0
m
== #(
    Ab: "hello"
    aB: 0
    ab: 10
)
set/case 'm/ab 192.168.0.1
== #(
    Ab: "hello"
    aB: 0
    ab: 192.168.0.1
)

m: #(%cities.red 10)
extend m [%cities.red 99 %countries.red 7 %states.red 27]
m
== #(
    %cities.red 99
    %countries.red 7
    %states.red 27
)

6. 删除键

要删除映射中的键值对,你只要简单地以一种可用的方式设置键为 none 即可。

例:

m: #(a: 1 b 2 "c" 3 d: 99)
m
== #(
    a: 1
    b: 2
    "c" 3
    d: 99
)
m/b: none
put m "c" none
extend m [d #[none]]
m
== #(
    a: 1
)
注意

上面例子中的构造语法是必需的,这是为了要传递一个 none! 值而不是一个 word! 值(仅是一种其所需构造 spec 区块的方式)。

也可以使用 clear 动作来一次性删除所有键:

clear #(a 1 b 2 c 3)
== #()

7. 反射

  • find 检查一个键是否有定义在映射中,如果找到则返回 true,否则返回 none

find #(a 123 b 456) 'b
== true
  • length? 返回映射中键值对的个数。

length? #(a 123 b 456)
== 2
  • keys-of 以区块形式返回映射中的键的列表(设词会被转换为单词)。

keys-of #(a: 123 b: 456)
== [a b]
  • values-of 以区块形式返回映射中的值的列表。

values-of #(a: 123 b: 456)
== [123 456]
  • body-of 以区块形式返回映射中的所有键值对。

body-of #(a: 123 b: 456)
== [a: 123 b: 456]

results matching ""

    No results matching ""