背景:
阅读文章

LPC基础数据类型:array和mapping

[日期:2008-12-25] 来源:  作者:泥巴创世纪 [字体: ]

MudOS 提供了一种叫做 mapping 的数据类型,mapping
是和其他语言(例如Perl)中的联合数组等价的。联合数组与
标准的数组的分别在于,联合数组可以用任意的数据类型来
建立索引(如 string、object、int、array 等等)而不是仅
仅用整数。另外,联合数组是一种“稀疏”的数组,因为一
个 mapping 可以给第 1,000,000 个元素赋值而不给其他所


有的元素赋值。mapping 有两个独特的好用处:

1、数据库
2、代替“struct”类型

一个 mapping 是这样声明的:

mapping x;

一个 mapping 可以这样来初始化:

  x = ([ key0 : value0, key1 : value1, ... ]);

  (注意:“x = ([]);”可用于创建一个空的 mapping)

注意,一个 mapping必须在你给它分配任何元素之前初始化,
这个限制是因为 MudOS将所有的变量(无论什么类型)都初始
化为 0,如果你不预先初始化一个 mapping,当你尝试给这
个 mapping 分配元素时,你将看到“Indexing on illegal
type”这样的出错信息。

新的 (key, value) 对照可以这样加入 mapping 中:

x[key] = value;

上面这种方式使得 driver 为了指定的键,去寻找一个叫做
“x”的 mapping,如果这个 mapping 里面已经有了这个键,
那么 mapping 中这个键对应的值就被替换为等号右边的值。
如果 mapping 中还没有这个值, 一块额外的空间将被自动
(动态的)分配出来,然后这个 (key, value) 的对照将被插
入这个 mapping 中。

一个映射中的元素可以像下面这样来引用:

    write(x[key] + "\n");

一个映射中的元素可以像下面这样来删除:

    map_delete(x, key);

这种删除的方式将会导致下面的表达式返回真(1):

    undefinedp(x[key])

因此你可以像这样写段程序:

if (undefinedp(value = x["MudOS"]))
{
    write("“MudOS”并未在映射“x”中用作一个"
        "键。\n");
} else
{
    write("“MudOS”键的值是:" + value + "。"
        "\n");
}

映射中键(索引)的列表可以用 keys() efun 来获得, 比如
说:

    mixed *idx;
    mapping x;

    x = ([ "x" : 3, "y" : 4]);
    idx = keys(x);

idx == ({ "x", "y" }) 或 ({ "y", "x" })。

注意,key() 返回的索引列表是明显用一个随机的顺序排列
的(这个顺序是储存 mapping 的一个副作用)。

映射中值(value)的列表可以用 values() efun 来获得,比
如说:

    idx = values(x);

这样 idx 将会等于 ({ 3, 4 }) 或 ({ 4, 3 })。
注意,values() 返回的值的顺序是与 keys()返回的键的顺
序一致的。

映射中(key, value)的对照可以用 each() efun一次次的传
回, 当到达了映射的结尾时,each() 会返回一个空的向量
(0, 0)。each() 返回的顺序是和 key()、values() 的顺序
一致的。例如:

    mixed *pair;

    while ((pair = each(x)) != ({ }))
    {
          write("key   = " + pair[0] + "\n");
          write("value = " + pair[1] + "\n");
    }

(注:MudOS v22 中 each() 函数已经被去掉)。

映射可以是二维的(如果有必要,也可以是多维的),就和数
组一样。

    mapping x, y;

    x = ([ ]);
    y = ([ ]);

    y["a"] = "c";
    x["b"] = y;

结果 x["b"]["a"] == "c"

映射也可以使用“*”运算符:

    mapping r1, r2, a;

    r1 = ([ ]);
    r2 = ([ ]);

    r1["driver"] = "mudlib";
    r2["mudlib"] = "castle";

因此:

    a = r1 * r2

使 a 变成这样一个映射:a["driver"] == "castle";

你也可以把两个映射加起来,两个映射的和就是把它们联合
起来。

    a = r1 + r2

这样 a 变成了:
a["driver"] == "mudlib" 而且 a["mudlib"] == "castle"

+= 运算符也是支持的,因此你可以这样用:

    a += ([ key : value ]);

可以替代:

    a[key] = value;

可是,后面的方法会有效率得多,因为前面的要先创建一个
新的映射,再把它们俩加起来,而后面的不必。

映射中减运算符应该并没有定义,你可以用 map_delete()。

sizeof() 这个 efun 可以用于测定这个 mapping 中一共有
多少对(key, value)对照。

    write("映射“x”包括" + sizeof(x) + "个元素"
        "。\n");

执行方式:

MudOS 的 mapping是使用一个可扩展的哈希表来实现的,这
个哈希表的容量通常是两倍的,就是说当此哈希表的使用率
趋近于满的时候,哈希表的容量将被扩展为原先的两倍,以
保证它存取的效率。

制作者:

MudOS 的 mapping类型最初由 Whiplash@TMI 完成,一部分
的内容在后来由 Truilkan@TMI重写过(为了使用一个可扩展
哈希表来代替 2 杈树)。

实现 mapping 的一部分数据结构是基于 Larry Wall的Perl
语言中的 hash.c 模块。Perl 程序包是由 GNU Copyleft的
GPL(General Public License)保护的。

翻译使用的词汇:

associative   :联合
key         :键
dynamically   :动态
mapping       :映射
implementation :执行

映射mapping是没有序列的,不要想用 mapping 序列来访问成员,你必须通过关键字keys()、values()来访问,还有mapping 成员不需要声明类型,完全根据赋值情况而定。array数组是有排序的,如果数组没有进行过运算,那么它的序列总是不变的,这和书写的时候有关,因此array数组可以用序列来访问成员。
收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论