2

我有一本字典:

   Dictionary<ICD_Map2, string> maps = new Dictionary<ICD_Map2, string>();

    public class ICD_Map2
    {
        public string call_type {get; set; }
        public string destination{get; set;} 

    }

maps.Add(new ICD_Map2() {call_type = "Mobile SMS", destination = "Australia"},"Local Text");
maps.Add(new ICD_Map2() {call_type = "Mobile SMS", destination = "International"},"International Text");

所以我想要的是,当我传递两个变量时:

案例 1 variable1 = "Mobile SMS" && variable2 = "Australia" 我想要一个函数返回 "Local Text"

案例 2“国际文本”取决于我的输入变量匹配 ICD_Map2 定义“移动短信”和“国际”。`

如何构造此映射函数以从一组结果中返回集合中的第一个(如果有多个结果)?这是一个非常简化的示例,我有超过 100 个映射。

4

5 回答 5

3

虽然有很多方法可以实现这一点,但我个人使用的最快和最简单的 LINQ 是FirstOrDefault这样的:

string var1 = "Mobile SMS";
string var2 = "Australia";

var item = maps.FirstOrDefault(e => e.Key.call_type == var1 && e.Key.destination == var2);
string result = (item == null) ? "No value" : item.Value;

在这种情况下,如果没有相应的匹配项,您最终会result为 null。

于 2012-10-29T08:26:12.860 回答
3

要使用字典,键需要支持相等操作。例如:

public class ICD_Map2 : IEquatable<ICD_Map2>
{
    public ICD_Map2(string callType, string destination) {
        CallType = callType;
        Destination = destination;
    }
    public override int GetHashCode() {
        int result = 17;
        result = -13 * result +
            (CallType == null ? 0 : CallType.GetHashCode());
        result = -13 * result +
            (Destination == null ? 0 : Destination.GetHashCode());
        return result;
    }
    public override bool Equals(object other) {
        return Equals(other as ICD_Map2);
    }
    public bool Equals(ICD_Map2 other) {
        if(other == null) return false;
        if(other == this) return true;
        return CallType == other.CallType && Destination == other.Destination;
    }
    public string CallType {get; private set; }
    public string Destination{get; private set;} 
}

注意将其设为只读是有意的:可变键会导致巨大的问题 - 避免这种情况。

现在您可以将其用作键,例如:

var key = new ICD_Map2("Mobile SMS", "Australia");
string result;
if(maps.TryGetValue(key, out result)) {
    Console.WriteLine("found: " + result);
}

反向查找是有问题的,除非您有第二个字典,否则无法优化。一个简单的操作(性能 O(n))将是:

string result = "International Text";
var key = (from pair in maps
           where pair.Value == result
           select pair.Key).FirstOrDefault();
if(key != null) {
    Console.WriteLine("found: " + key);
}

把它们放在一起:

static void Main()
{
    Dictionary<ICD_Map2, string> maps = new Dictionary<ICD_Map2, string> {
        {new ICD_Map2 ("Mobile SMS", "Australia"),"Local Text"},
        {new ICD_Map2 ("Mobile SMS", "International"),"International Text"}
    };

    // try forwards lookup
    var key = new ICD_Map2("Mobile SMS", "Australia");
    string result;
    if (maps.TryGetValue(key, out result))
    {
        Console.WriteLine("found: " + result);
    }

    // try reverse lookup (less efficient)
    result = "International Text";
    key = (from pair in maps
               where pair.Value == result
               select pair.Key).FirstOrDefault();
    if (key != null)
    {
        Console.WriteLine("found: " + key);
    }
}
于 2012-10-29T08:27:43.167 回答
2

构建自定义比较器:

public class CusComparer: IEqualityComparer<ICD_Map2>
{
    public bool Equals(ICD_Map2 x, ICD_Map2 y)
    {
        return x.call_type.Equals(y.call_type) 
              && x.destination.Equals(y.destination);
    }

    public int GetHashCode(ICD_Map2 obj)
    {
        return obj.call_type.GetHashCode() 
                 ^ obj.destination.GetHashCode();
    }
}

请记住,Dictionary还有另一个带有 accepting 的重载构造函数IEqualityComparer

var maps = new Dictionary<ICD_Map2, string>(new CusComparer());

maps.Add(new ICD_Map2() {
              call_type = "Mobile SMS", 
              destination = "Australia"},
         "Local Text");

maps.Add(new ICD_Map2() {
            call_type = "Mobile SMS", 
            destination = "International"},
         "International Text");

所以你可以得到:

 var local = maps[new ICD_Map2() {
                     call_type = "Mobile SMS", 
                     destination = "Australia"}];
于 2012-10-29T08:27:59.483 回答
0

我认为这应该可行,将在几秒钟内仔细检查:

maps.Where(a => (String.IsNullOrEmpty(var1) || String.Compare(a.Key.call_type, var1) == 0) 
             && (String.IsNullOrEmpty(var2) || String.Compare(a.Key.destination, var2) == 0))
    .FirstOrDefault().Value`
于 2012-10-29T08:22:58.710 回答
0

您必须在 ICD_Map2 上实现 IEquitable 接口并覆盖 GetHashCode 函数(最好也覆盖 Equals(object) ,因为 Dictionary 使用通用 IEquitable 接口来查找密钥不是必需的)

于 2012-10-29T08:24:40.463 回答