在d中存储关联数组的键

时间:2014-04-02 17:54:56

标签: arrays d

示例代码:

import std.stdio;

void main() {
    auto a = ["one":1, "two":2, "three":3];
    writeln(a);
}

但输出:

["three":3, "one":1, "two":2]

默认情况下,D优化存储密钥。如何禁用或重新实现它?

2 个答案:

答案 0 :(得分:1)

那么,你是抱怨打印出来的订单与插入订单不符?关联数组是哈希表。没有秩序。 C ++ 11中的等效类型称为unordered_map,特别是因为哈希表没有顺序。如何在表中放置键/值对完全基于键的哈希值。如果表被重新定义,它们在表中的顺序甚至可以完全改变。为了使哈希表保留用于打印或任何其他目的的插入顺序,它必须按插入顺序维护单独的密钥列表,这将是额外的开销,大多数人不需要,因此它不会有意义的是将其纳入核心AA实施中。

因此,如果您想维护插入顺序,您将不得不在一个单独的数据结构中自行维护 - 例如保留一个已插入哈希表的所有键的数组,当您将其添加到AA时,将该键附加到数组,并在从AA中删除该键时将其从数组中删除。

以下是按特定顺序打印AA的键/值对的一种可能实现:

import std.stdio;

auto orderKeys(int[string] hashTable, string[] keys)
{
    import std.array;

    static struct Range
    {
        @property bool empty() @safe const pure nothrow { return _keys.empty; }

        @property auto front() @trusted const pure
        {
            static struct PrettyPrintTuple
            {
                string toString() @trusted pure
                {
                    import std.string;
                    return format(`"%s":%s`, key, value);
                }

                string key;
                int value;
            }

            return PrettyPrintTuple(_keys.front, _hashTable[_keys.front]);
        }

        void popFront() @safe pure nothrow
        {
            _keys.popFront();
        }

        int[string] _hashTable;
        string[] _keys;
    }

    return Range(hashTable, keys);
}

void main()
{
    auto a = ["one":1, "two":2, "three":3];
    writeln(orderKeys(a, ["one", "two", "three"]));
}

不是单独维护一个AA和一个数组,而是拥有一个包含AA和数组的包装类型会更清晰,你可以在其上调用函数来添加,删除或访问元素,从而管理数组,以便它与插入顺序中AA当前的键完全匹配(而上面的范围假定所有键都在AA中),但我会把这个练习留给你。

答案 1 :(得分:0)

D关联数组不保留插入顺序。 您可以在此处找到更多信息(和实施):

http://forum.dlang.org/thread/xbanhtkvrizyqjcibsck@forum.dlang.org#post-51F9327D.2020704:40esperanto.org.ar

http://forum.dlang.org/thread/dfyowpjhdaemhxhepfmk@forum.dlang.org?page=3

顺便说一句。我有一些更好的OrderedAA实现,所以如果你希望我可以公开它(如果我发现它:))