键值对数据结构的最佳实现方式是什么?

79

最近我在研究C#,但是所有的泛型集合让我有点困惑。假设我想要表示一个数据结构,其中树的头部是一个键值对,然后下面有一个可选的键值对列表(但没有比这更多的级别)。这样做是否合适?

public class TokenTree
{
    public TokenTree()
    {
        /* I must admit to not fully understanding this,
         * I got it from msdn. As far as I can tell, IDictionary is an
         * interface, and Dictionary is the default implementation of
         * that interface, right?
         */
        SubPairs = new Dictionary<string, string>();
    }

    public string Key;
    public string Value;
    public IDictionary<string, string> SubPairs;
}

它实际上只是用于传递数据的简单分流器。

9个回答

143

有一种实际的数据类型叫做KeyValuePair,使用方法如下

KeyValuePair<string, string> myKeyValuePair = new KeyValuePair<string,string>("defaultkey", "defaultvalue");

1
这在使用"using"语句时非常好用(类似于旧的typedef),以便节省一些打字并使一切更清晰。如果您经常使用例如(string, string)对。 - Andreas Reiff
8
KeyValuePair<string, string> NAME_HERE = new KeyValuePair<string,string>("defaultkey", "defaultvalue"); - HasanAboShally
1
为了补充@AndreasReiff的评论:在每个需要(string, string)结构体的文件顶部使用 using NameValuePair = System.Collections.Generic.KeyValuePair<string, string>;。虽然我发现在我的命名空间中创建一个 class NameValuePair 更方便: public class NameValuePair { KeyValuePair it; public NameValuePair( string name, string value ) { it = new KeyValuePair( name, value ); } public string Name { get { return it.Key; } } public string Value { get { return it.Value; } } } - ToolmakerSteve

14

你可以直接使用字典对象,然后通过扩展它来进行自己的修改。

public class TokenTree : Dictionary<string, string>
{
    public IDictionary<string, string> SubPairs;
}

这样做的好处是您不必强制实施IDictionary的规则(例如,键的唯一性等)。

是的,你对构造函数的概念理解正确 :)


7
我认为你想要的是(作为你问题的文字实现):

我认为你可能需要的是:

public class TokenTree
{
    public TokenTree()
    {
        tree = new Dictionary<string, IDictionary<string,string>>();
    }

    IDictionary<string, IDictionary<string, string>> tree; 
}

根据你的问题,你实际上是要求一个键值对“列表”,因此你可能需要将内部的IDictionary替换为:

IList<KeyValuePair<string, string>>

5

有一个内置类型叫做KeyValuePair。实际上,当您在IDictionary中进行迭代时,这就是您访问的内容。

此外,这个结构几乎不是一棵树,找到一个更具代表性的名称可能是一个很好的练习。


3
只有一件事情需要补充(虽然我认为其他人已经回答了你的问题)。为了可扩展性(因为我们都知道这种情况肯定会发生),您可能希望查看组合模式。这非常适合处理“树状结构”。

就像我说的,我知道你只期望一个子级别,但如果您以后需要扩展,这真的很有用^_^


2

@Jay Mooney: 在.NET中,泛型Dictionary类实际上是一个哈希表,只是类型固定了。

你展示的代码不应该说服任何人使用Hashtable而不是Dictionary,因为这两个代码片段都可以用于两种类型。

对于哈希表:

foreach(object key in h.keys)
{
     string keyAsString = key.ToString(); // btw, this is unnecessary
     string valAsString = h[key].ToString();

     System.Diagnostics.Debug.WriteLine(keyAsString + " " + valAsString);
}

对于字典:

foreach(string key in d.keys)
{
     string valAsString = d[key].ToString();

     System.Diagnostics.Debug.WriteLine(key + " " + valAsString);
}

对于使用KeyValuePair的另一个示例,使用非泛型版本的Hashtable,使用泛型版本的Dictionary。

因此,两种方法同样简单,但是Hashtable使用Object作为键和值,这意味着您将装箱所有值类型,并且没有类型安全性,而Dictionary使用泛型类型,因此更好。


1
使用类似这样的代码:
class Tree < T > : Dictionary < T, IList< Tree < T > > >  
{  
}  

虽然不太美观,但我认为它会给你想要的结果。很遗憾KeyValuePair是密封的。


1

词典类正是你想要的,对吧。

你可以直接将字段声明为Dictionary,而不是IDictionary,但这取决于你自己。


1
键值对是C#中的一种数据类型。你可以像这样使用它:
List<KeyValuePair<string, string>> arrFileName = new List<KeyValuePair<string, string>>(); 

你可以迭代这个列表并访问键和值。
foreach (KeyValuePair<string, string> ele in arrFileName)
{ FileName = ele.Key;
  string filepath = ele.Value;} I have used it for accessing filename and filepath.                   

感谢您对贡献Stack Overflow社区的兴趣。这个问题已经有了相当多的答案,其中一个已经得到社区广泛验证。您确定您的方法之前没有被提及过吗?如果是这样的话,解释一下您的方法与众不同的地方、在什么情况下可能更适用以及为何您认为之前的答案不够满意将会很有帮助。您是否可以友好地编辑您的答案来提供解释? - Jeremy Caney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接