Hashtable / Dictionary但是键由多个值组成?

时间:2010-03-02 21:10:11

标签: .net dictionary hashtable

假设我有一个具有stringProp1,stringProp2的对象。我希望将stringProp1,stringProp2的每个组合存储在Dictionary中。最初我将密钥存储为key = stringProp1 + stringProp2,但实际上这可能会导致错误,具体取决于2个值。是创建自定义字典类的最佳解决方案,还是使用内置.NET类的更好方法?

6 个答案:

答案 0 :(得分:3)

在.NET 4中,您可以使用System.Tuple作为密钥。

var dict = new Dictionary<Tuple<string,string>, int>();
dict.Add(Tuple.Create("foo","bar"), 1);

答案 1 :(得分:1)

为什么不直接使用包含2个字符串的结构?这将是最简单的。

答案 2 :(得分:1)

只要密钥包含比较器正确比较/散列的必要信息,您使用哪种数据结构并不重要。

您甚至可以将对象用作字典中的键,并使用适当的EqualityComparer实现在您喜欢的任何字段上进行比较。这个使用序数比较比较两个字符串属性:

class MyObject
{
    public string StringProp1 { get; set; }
    public string StringProp2 { get; set; }
    public MyObject(string prop1, string prop2)
    {
        StringProp1 = prop1;
        StringProp2 = prop2;
    }
}

class MyObjectComparerS1S2 : EqualityComparer<MyObject>
{
    //Change this if you need e.g. case insensitivity or 
    //culture-specific comparisons
    static StringComparer comparer = StringComparer.Ordinal;

    public override bool Equals(MyObject x, MyObject y)
    {
        return 
            comparer.Equals(x.StringProp1, y.StringProp1) &&
            comparer.Equals(x.StringProp2, y.StringProp2);
    }

    public override int GetHashCode(MyObject obj)
    {
        //Uncomment this if running in a checked context
        //Copycat of Jon Skeet's string hash combining
        //unchecked
        //{
            return 
                (527 + comparer.GetHashCode(obj.StringProp1)) * 31 +
                comparer.GetHashCode(obj.StringProp2);
        //}
    }

    public static readonly MyObjectComparerS1S2 Instance = 
        new MyObjectComparerS1S2();

}

static void Main(string[] args)
{
    Dictionary<MyObject, MyObject> dict = 
        new Dictionary<MyObject, MyObject>(MyObjectComparerS1S2.Instance);
    MyObject obj = new MyObject("apple", "plum");
    dict.Add(obj, obj);
    MyObject search = new MyObject("apple", "plum");
    MyObject result = dict[search];
    Console.WriteLine("{0}:{1}", result.StringProp1, result.StringProp2);
}

您可以通过创建虚拟对象,填充字符串键并使用虚拟对象作为查找键来搜索对象。 如果您不喜欢这个想法,或者它不可行,只需按@Vlad说并在结构或类中提取键。在这种情况下,修改比较器以从EqualityComparer<MyKeyStructOrClass>派生。

请注意,我已使用Jon Skeet's method来组合字符串哈希。它可能比XOR method found on MSDN更好。如果您觉得钢筋不足,请随意使用另一个哈希实现处理字符串 - HsiehMurmurBob Jenkin's或您信任的任何内容。这是{{3实际上也有一些C#代码。

答案 3 :(得分:1)

根据您填写字典的方式以及使用它执行的操作,可以使用匿名类型作为键。例如,如果您有一个班级Person

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

如果你有一个这样的序列,IEnumerable<Person>,并想创建一个将名字映射到年龄的字典,你可以写:

var personDictionary = people.ToDictionary(p => new { p.FirstName, p.LastName });

这会为您提供一个字典,其中包含名字和姓氏作为键,并将整个Person存储为值。您可以稍后使用以下方式查找密钥:

personDictionary.TryGetValue(new { FirstName = "John", LastName = "Smith" },
    out person);

如果您尝试在不同的类甚至方法之间传递字典,这对您没有多大帮助,它变得难以管理,但是为了在单个方法中进行一些快速数据处理,它可以很好地工作。事实上,使用匿名类作为GroupBy扩展方法或group by查询理解语法的关键是很常见的。

答案 4 :(得分:0)

如果有一个字符在任何一个字符串中都没有出现,你可以在那里放一个分隔符。

例如

stringProp1 + "|" + stringProp2

如果没有,那么我建议{/ 1}},如

Dictionary<string, Dictionary<string, MyValueType>>

答案 5 :(得分:0)

您可以使用MD5算法为每个字符串生成一个值,然后将这两个值相加。结果就是关键 .NET在System.Security.Cryptography命名空间中提供类MD5CryptoServiceProvider。该类包含用于计算哈希值的ComputeHash方法。