从Dictionary <tkey,string =“”> instance </tkey,> </tkey,>中提取字典<tkey,double =“”>

时间:2012-01-26 15:32:54

标签: c# .net linq generics

我有一个通用词典,其中TValue的类型为StringDictionary<int, string>)。我选择使用字符串作为值类型,因为数据是从Xml文件加载的,其中源值可以是字符或数字数据类型(我认为Object也是可接受的TValue类型,但即便如此这个问题同样适用)。

字符数据类型也很重要,因此不能直接排除它们。

我想提取这个Dictionary<int, double>的一个子集。换句话说,我想要字典的子集,其中值是数字。

现在我这样做:

Dictionary<int, string> myDictionary;
// Do some loading.
var numericData = myDictionary.Where(kvp => Double.TryParse(kvp.Value, out temp)       

这种方法非常难看,并没有让我得到结果Dictionary<int, double>任何人都可以提供其他方法来改善这一点吗?

谢谢!

2 个答案:

答案 0 :(得分:6)

您提供的代码不仅丑陋 - 在执行时它会失败InvalidCastException。我怀疑你真的想要:

var numericData = myDictionary
        .Select(kvp => {
                    double value;
                    return new { kvp.Key,
                        Value = double.TryParse(kvp.Value, out value) 
                                   ? value : (double?) null
                    };
               })
        .Where(pair => pair.Value != null)
        .ToDictionary(pair => pair.Key, pair => pair.Value.Value);

是的,那很难看 - 但是:

  • 避免多次解析该值
  • 避免在您的查询中添加副作用

如果您愿意解析两次,可以使它更清晰但效率更低:

var numericData = myDictionary
       .Where(kvp => { double tmp; return double.TryParse(kvp.Value, out tmp); })
       .ToDictionary(pair => pair.Key, pair => double.Parse(pair.Value));

或者(更干净地)你可以创建一个单独的方法:

public static double? TryParseNullableDouble(string text)
{
    double value;
    return double.TryParse(text, out value) ? value : (double?) null;
}

然后第一个版本变为:

var numericData = myDictionary
        .Select(kvp => new { kvp.Key, TryParseNullableDouble(kvp.Value) })
        .Where(pair => pair.Value != null)
        .ToDictionary(pair => pair.Key, pair => pair.Value.Value);

答案 1 :(得分:0)

您可以使用包含double值的temp变量创建一个新字典 - 这会利用字典的枚举和添加逐项完成的事实,因此temp包含正确的double值:< / p>

double temp = 0;
var numDict = myDictionary.Where(kvp => Double.TryParse(kvp.Value, out temp))
                          .ToDictionary( x=> x.Key, x=> temp);