C#中带有多维键的哈希表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/689940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 13:37:16  来源:igfitidea点击:

Hashtable with MultiDimensional Key in C#

c#dictionaryhashtable

提问by Scott Schulthess

I'm basically looking for a way to access a hashtable value using a two-dimensional typed key in c#.

我基本上是在寻找一种在 c# 中使用二维类型键访问哈希表值的方法。

Eventually I would be able to do something like this

最终我将能够做这样的事情

HashTable[1][false] = 5;
int a = HashTable[1][false];
//a = 5

This is what I've been trying...hasn't worked

这是我一直在尝试的……没有奏效

Hashtable test = new Hashtable();
test.Add(new Dictionary<int, bool>() { { 1, true } }, 555);
Dictionary<int, bool> temp = new Dictionary<int, bool>() {{1, true}};
string testz = test[temp].ToString(); 

采纳答案by JaredPar

I think a better approach is to encapsulate the many fields of your multi-dimensional key into a class / struct. For example

我认为更好的方法是将您的多维键的许多字段封装到一个类/结构中。例如

struct Key {
  public readonly int Dimension1;
  public readonly bool Dimension2;
  public Key(int p1, bool p2) {
    Dimension1 = p1;
    Dimension2 = p2;
  }
  // Equals and GetHashCode ommitted
}

Now you can create and use a normal HashTable and use this wrapper as a Key.

现在您可以创建和使用普通的 HashTable 并将此包装器用作键。

回答by Jason Punyon

I think this might be closer to what you're looking for...

我认为这可能更接近你正在寻找的......

var data = new Dictionary<int, Dictionary<bool, int>>();

回答by David M

I would suggest that you create a small custom class exposing the bool and int properties, and override its GetHashCode and Equals methods, then use this as the key.

我建议您创建一个公开 bool 和 int 属性的小型自定义类,并覆盖其 GetHashCode 和 Equals 方法,然后将其用作键。

回答by Mike

You might be able to "double-nest" your hashtables - in other words, your main Dictionary is of type Dictionary<int, Dictionary<bool, my_return_type>>.

您也许可以“双重嵌套”您的哈希表 - 换句话说,您的主 Dictionary 的类型为Dictionary<int, Dictionary<bool, my_return_type>>

That accomplishes your goal of being able to use the double bracket notation in your first code snippet.

这实现了您能够在第一个代码片段中使用双括号表示法的目标。

Of course, the management side is a little trickier. Every time you add an entry, you need to test if the main dictionary contains a dictionary for the primary key, and add a new dictionary if not, then add the secondary key and value to the inner Dictionary.

当然,管理方面有点棘手。每次添加条目时,需要测试主字典是否包含主键的字典,如果没有则添加新字典,然后将辅助键和值添加到内部字典中。

回答by JaredPar

How about using a regular Dictionary with some kind of Tuple structure as a key?

如何使用具有某种元组结构的常规字典作为键?

public class TwoKeyDictionary<K1,K2,V>
{
    private readonly Dictionary<Pair<K1,K2>, V> _dict;

    public V this[K1 k1, K2 k2]
    {
        get { return _dict[new Pair(k1,k2)]; }
    }

    private struct Pair
    {
        public K1 First;
        public K2 Second;

        public override Int32 GetHashCode()
        {
            return First.GetHashCode() ^ Second.GetHashCode();
        }

        // ... Equals, ctor, etc...
    }
}

回答by Andrew Hare

Could you use a Dictionary<KeyValuePair<int,bool>,int>?

你能用Dictionary<KeyValuePair<int,bool>,int>吗?

回答by bruno conde

Wrap your two-dimensional key in a separate typeand use that type as a key. Also consider overriding GetHashCode()and Equals()methods. Preferably use Dictionary<>instead of HashTablesince apparently you can use that.

将您的二维密钥单独包装起来,type并将该类型用作密钥。还要考虑覆盖GetHashCode()Equals()方法。最好使用Dictionary<>而不是HashTable因为显然你可以使用它。

回答by Paul Ruane

A quick and dirty way would be to create a composite key from the two pieces of information, e.g.

一种快速而肮脏的方法是从两条信息中创建一个复合键,例如

IDictionary<string, int> values = new Dictionary<string, int>();
int i = ...;
bool b = ...;
string key = string.Concat(i, '
public class MyDict
{
    private readonly IDictionary<string, int> values = new Dictionary<string, int>();

    public int this[int i, bool b]
    {
        get
        {
            string key = BuildKey(i, b);
            return values[key];
        }

        set
        {
            string key = BuildKey(i, b);
            values[key] = value;
        }
    }

    private static string BuildKey(int i, bool b)
    {
        return string.Concat(i, '
public class KeyPair<Tkey1, Tkey2>
{
    public KeyPair(Tkey1 key1, Tkey2 key2)
    {
        Key1 = key1;
        Key2 = key2;
    }

    public Tkey1 Key1 { get; set; }
    public Tkey2 Key2 { get; set; }

    public override int GetHashCode()
    {
        return Key1.GetHashCode() ^ Key2.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        KeyPair<Tkey1, Tkey2> o = obj as KeyPair<Tkey1, Tkey2>;
        if (o == null)
            return false;
        else
            return Key1.Equals(o.Key1) && Key2.Equals(o.Key2);
    }
}
', b); } }
', b); values[key] = 555;

To encapsulate this a bit better you could wrap the dictionary:

为了更好地封装它,您可以包装字典:

public class KeyPairDictonary<Tkey1, Tkey2, Tvalue> 
    : Dictionary<KeyPair<Tkey1, Tkey2>, Tvalue>
{
    public Tvalue this[Tkey1 key1, Tkey2 key2]
    {
        get
        {
            return this[new KeyPair<Tkey1, Tkey2>(key1, key2)];
        }
        set
        {
            this[new KeyPair<Tkey1, Tkey2>(key1, key2)] = value;
        }
    }
}

To make this more robust, encapsulate the composite key as a type, e.g. a class that contains the two fields, ensuring you override the Equals() and GetHashCode() methods correctly.

为了使其更健壮,将复合键封装为一种类型,例如包含两个字段的类,确保您正确覆盖 Equals() 和 GetHashCode() 方法。

回答by AndreasN

You need a key class for the Dictonarythat implements GetHashCodecorrectly. And you can extend Dictonaryto let you access it in a friendly way.

您需要一个正确Dictonary实现的关键类GetHashCode。并且您可以扩展Dictonary以让您以友好的方式访问它。

The KeyPairclass:

KeyPair类:

KeyPairDictonary<int, bool, string> dict = 
    new KeyPairDictonary<int, bool, string>();

dict[1, false] = "test";
string test = dict[1, false];

Extend Dictonary<>:

扩展Dictonary<>

public class MultiDictionary<K1, K2, V>
{
    private Dictionary<K1, Dictionary<K2, V>> dict = 
        new Dictionary<K1, Dictionary<K2, V>>();

    public V this[K1 key1, K2 key2]
    {
        get
        {
            return dict[key1][key2];
        }

        set
        {
            if (!dict.ContainsKey(key1))
            {
                dict[key1] = new Dictionary<K2, V>();
            }
            dict[key1][key2] = value;
        }
    }
}

You can use it like this:

你可以这样使用它:

##代码##

回答by AndreasN

I'd suggest a slight variation on jachymko's solution which will allow you to avoid creating a class for key pairs. Instead, wrap a private dictionary of dictionaries, as so:

我建议对 jachymko 的解决方案稍作修改,这样您就可以避免为密钥对创建一个类。相反,包装一个私人字典字典,如下所示:

##代码##