当前位置:  开发笔记 > 编程语言 > 正文

C#中使用MultiDimensional键的Hashtable

如何解决《C#中使用MultiDimensional键的Hashtable》经验,为你挑选了6个好方法。

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

最终我可以做这样的事情

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

这就是我一直在尝试的......没有用

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

JaredPar.. 68

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

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

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



1> JaredPar..:

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

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

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


不要忘记你需要覆盖GetHashCode和Equals以在Hashtable中使用它.
@David,不是这种情况.Equals的默认实现只对在这种情况下工作的所有字段执行相等.GetHashcode可能不如用户所希望的那样高效,但它也可以使用默认实现.
@David,据说,实际上这通常是一种好习惯.
@JaredPar这样做是值得的.我们最近发现了`struct`类型的`GetHashCode`的默认实现的性能问题.手动实现完全消除了这个瓶颈.此外,虽然是一个不同的解决方案,但我们发现"字典中的字典"方法在所有常见操作(`Dictionary >`)上运行得更快.但是,这不允许复合键的空部分,而上面的`struct` /`class`键可以很容易地允许空值而不需要任何额外的工作.

2> 小智..:

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

public class TwoKeyDictionary
{
    private readonly Dictionary, 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...
    }
}


@Mugen Tuples在09年不在身边.
您不必实现Pair,使用System.Tuple

3> Hüseyin Yağl..:

您现在可以使用新元组在C#7.0中执行此操作:

// Declare
var test = new Dictionary<(int, bool), int>();

// Add
test.Add((1, false), 5);

// Get
int a = test[(1, false)];



4> 小智..:

以防万一有人最近在这里,如一个评论者所描述的,如何在.Net 4.0中快速而肮脏的方式这样做的例子.

class Program
{
  static void Main(string[] args)
  {
     var twoDic = new Dictionary, String>();
     twoDic.Add(new Tuple(3, true), "3 and true." );
     twoDic.Add(new Tuple(4, true), "4 and true." );
     twoDic.Add(new Tuple(3, false), "3 and false.");

     // Will throw exception. Item with the same key already exists.
     // twoDic.Add(new Tuple(3, true), "3 and true." );

     Console.WriteLine(twoDic[new Tuple(3,false)]);
     Console.WriteLine(twoDic[new Tuple(4,true)]);
     // Outputs "3 and false." and "4 and true."
  }
}



5> Jason Punyon..:

我想这可能更接近你正在寻找的东西......

var data = new Dictionary>();



6> 小智..:

我建议jachymko的解决方案略有不同,这将允许您避免为密钥对创建一个类.而是包装一个字典的私人字典,如下所示:

public class MultiDictionary
{
    private Dictionary> dict = 
        new Dictionary>();

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

        set
        {
            if (!dict.ContainsKey(key1))
            {
                dict[key1] = new Dictionary();
            }
            dict[key1][key2] = value;
        }
    }
}


不是出于任何效率原因,而是因为我认为代码更简单(看看你必须忽略的).如果效率是主要关注点,那么我同意您的原始解决方案更好.我不喜欢像Pair 这样的类型,特别是当.NET 4.0将包含开箱即用的元组时.
为什么?我考虑了这一秒,但在我看来更糟糕,因为它有更大的开销(更多的GC压力,更糟糕的局部性)并且它没有任何好处 - 在哈希表中搜索具有平均恒定的时间效率,所以没有这样做了两次.
@jachymko如果效率被定义为速度而不是内存使用,那么使用更简单类型的字典解决方案中的直字典实际上会更快地执行.使用`struct`或其他类型创建的复合键导致性能下降,原因我尚未确定.
推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有