【问题标题】:Dictionary data structure that uses entry's field as a key使用条目的字段作为键的字典数据结构
【发布时间】:2014-01-10 10:09:48
【问题描述】:

某些类型的数据记录经常必须由唯一键索引。通常它看起来像这样(我使用 C#,因为它是我最熟悉的语言,但这个问题并不特定于它):

public class NamedRecord
{
    public readonly string UniqueImmutableName;
    ...
}

public class UsesUsualDict
{

    Dictionary<string, NamedRecord> myDict = new Dictionary<string, NamedRecord>();

    void AddRecord(NamedRecord _NewRecord)
    {
        myDict[_NewRecord.UniqueImmutableName] = _NewRecord;
    }

    NamedRecord GetRecord(string _Key)
    {
        return myDict[_Key];
    }

}

但是,这似乎有点多余:该字典中的键应始终被视为等于NamedRecord.UniqueImmutableName,但开发人员最终会自己维护这种关系。而且,我觉得这种数据重复不太合适。

有时我会看到类似的解决方案:数据记录甚至没有 UniqueImmutableName 作为其成员。例如,在他的tutorial for D language 中,Andrei Alexandrescu 使用数据结构来描述戏剧中角色的单词统计:

struct PersonaData {
   uint totalWordsSpoken;
   uint[string] wordCount;
}

但角色的名字甚至不在其中——它只能作为保存这些结构的字典的键。在该上下文之外,这个数据结构几乎没有用。

我想做的是这样的:

public class UsesLambdaDict
{
    LambdaDictionary<string, NamedRecord> myDict = new LambdaDictionary<string, NamedRecord>(NamedRecord _Record => _Record.UniqueImmutableName);

    void AddRecord(NamedRecord _NewRecord)
    {
        myDict.Add(_NewRecord);
    }

    NamedRecord GetRecord(string _Key)
    {
        return myDict[_Key];
    }
}

在我看来,这种处理此类数据记录的方式更好,因为 NamedRecord 的 UniqueImmutableName 成员和保存它的字典之间的关系是在编译时形式化的。我看到的缺点是无法确保给定的 lambda 将是一个纯函数,至少在 C# 中是这样。我不太了解D,但似乎pure关键字它也不能保证。

所以,我对此有几个问题:

  1. 这是一个真正的问题吗?我所拥有的第一个解决方案的缺点在一定程度上是理论上的——毕竟它可能没有任何问题。
  2. 还有哪些其他可能的解决方法?
  3. 建议的解决方案还有哪些其他可能的缺点?

【问题讨论】:

  • > C# ...但这个问题并不特定于它
  • 这个问题具体到哪种语言?
  • 它不特定于任何语言,但由于我使用C#并提到了D,所以我决定标记它们。

标签: oop data-structures dictionary d


【解决方案1】:

1.) 我不这么认为。

2.) 使用带有键和值的结构,我不认为 lambdas 是必要的

3.) 性能问题(缓存未命中)

【讨论】:

    【解决方案2】:

    1 - 开销还不够高,值得担心。由于字符串是引用类型且不可变,因此您不会存储两个字符串,而只是对同一字符串(或任何其他键)的附加引用。

    当然,您可以编写字典,这样您就不会分别存储键和值,而只存储值(然后在此对象中查找键)。但是,您最多可以节省 (PtrSize (4 or 8 bytes) * size of backing array)),这通常应该很小。另外,当您转到存储的对象以查找在哪里查找键值(可能在内存中的其他位置)时,您可能会得到间接,从而导致缓存未命中。

    如果您想自己编写字典来执行此操作,请查看这本免费电子书:

    http://www.syncfusion.com/resources/techportal/ebooks/datastructurespart2

    他们经历了如何散列这个,所以它应该很容易。或者,您可以从单声道项目源代码中复制。

    【讨论】:

    • 哦,我不担心内存占用。我只担心数据重复是因为逻辑含义,而不是因为它需要额外的空间。
    • 如果值是不可变的,你就不用担心(它永远不会改变,所以保留一个副本并不重要),如果值是可变的,那么你有一个更大的问题。如果值改变,hashcode 就会改变,然后它会在错误的 bin/not-looked-up 中正确)。您必须连接字典以在每次更新值时重新定位,这确实是要避免的。
    猜你喜欢
    • 2013-01-26
    • 2013-05-04
    • 2017-04-06
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    相关资源
    最近更新 更多