哈希表具有两个主键

3

如何使用 System.Collections 创建具有两个主键的集合?

我的意思是避免具有相同组合的新条目,但每个键可以与其他键一起使用(就像在 SQL 中组合两个主键一样)。


1
我认为你要找的术语是复合键或组合键。具有两个属性的键仍然只是一个键,而不是两个。 - nvogel
4个回答

5
您可以简单地使用一个 struct,例如:
struct CompositeKey<T1,T2>
{
  public T1 Item1;
  public T2 Item2;
}

然后将其用作关键字。


请注意,如果出于性能原因使用字典,则结构体可能无法按预期工作。请参阅“ValueType.GetHashCode的本机实现如何工作?”。 - johv
@johv:哈希码不需要唯一,而且.NET可以快速处理一些冲突。显然,太多的冲突会成为一个问题。 - leppie
我发现结构体的默认实现相当令人惊讶和不直观。我原本期望它更接近元组提供的功能。 - johv
@johv:而且我们还可以比较匿名类型 :) 我的方法只是为了展示一种非常简单的方式,应该能在95%的情况下使用。 - leppie
但这真的是“95%的时间都很好”吗?一个包含两个字符串的结构体的哈希码将如何计算?只使用第一个字符串吗?如果你所说的95%的时间是指线性搜索访问时间正常的情况,那么我想你是正确的。 - johv

2

如果你使用的是.NET 4.0,可以使用Tuple

否则,你可以自己创建一个Tuple。

在StackOverFlow上发现:C#中将元组(或数组)作为字典键

struct Tuple<T, U, W> : IEquatable<Tuple<T,U,W>>
{
    readonly T first;
    readonly U second;
    readonly W third;

    public Tuple(T first, U second, W third)
    {
        this.first = first;
        this.second = second;
        this.third = third;
    }

    public T First { get { return first; } }
    public U Second { get { return second; } }
    public W Third { get { return third; } }

    public override int GetHashCode()
    {
        return first.GetHashCode() ^ second.GetHashCode() ^ third.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }
        return Equals((Tuple<T, U, W>)obj);
    }

    public bool Equals(Tuple<T, U, W> other)
    {
        return other.first.Equals(first) && other.second.Equals(second) && other.third.Equals(third);
    }
}

2

就像LaGrandMere所说,如果你使用的是.NET 4.0或更高版本,你可以使用System.Tuple

Tuple<int,string> key = Tuple.Create(0, "Test");

另外,请注意,如果您将字符串、整数等作为字典中的键,您需要特殊处理在 SQL 中将是 NULL 的内容。字典中不能有空键。

var dict = new Dictionary<Tuple<string, int>, string>();

var address1 = Tuple.Create("5th Avenue",15);
var address2 = Tuple.Create("5th Avenue",25);
var address3 = Tuple.Create("Dag Hammarskjölds väg", 4);

dict[address1] = "Donald";
dict[address2] = "Bob";
dict[address3] = "Kalle";

// ...

int number = Int32.Parse("25");
var addressKey = Tuple.Create("5th Avenue",number);
string name = dict[addressKey]; // Bob

0

你也可以构建复合键,并在字典中使用它。

var compositeKey = key1.ToString()+key2.ToString();

var dict = new Dictionary<string,object>();
dict.Add(compositekey,val);

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