2016-08-03 40 views
1

我试图过滤,然后用一个元组作为键求和字典。 SO上有几个links,但没有任何广泛的。有什么建议吗?然后用元组作为键过滤然后求和字典

Dictionary<Tuple<int, string, string, int, string>, double> dctMC = new Dictionary<Tuple<int, string, string, int, string>, double>(); 
List<int> listIDs = new List<int> { 1, 3, 5 }; 

// ID, TYPE, NAME, ORDER, COLOUR, WEIGHT 
dctMC.Add(Tuple.Create(1, "Fruit", "Apple", 9, "Green"), 0.45); 
dctMC.Add(Tuple.Create(2, "Fruit", "Grape", 5, "Red"), 0.78); 
dctMC.Add(Tuple.Create(3, "Fruit", "Apple", 9, "Green"), 0.33); 
dctMC.Add(Tuple.Create(4, "Fruit", "Peach", 2, "Yellow"), 0.89); 
dctMC.Add(Tuple.Create(5, "Fruit", "Apple", 14, "Red"), 0.23); 

// Sum dictionary where IDs in listIDs, Type = FRUIT, Name = APPLE, Order = 9, Colour = "Green" 
double TOTAL = dctMC.Where(Z => listIDs.Contains(Z.Key(item1)) && 
           Z.Key(item2) == "Apple" && 
           Z.Key(item3) == 9 && 
           Z.Key(item4) == "Green") 
        .Sum() 
+0

适合添加初始化代码与值 - 使它更容易理解问题,并帮助你解决它:) –

回答

4

您的错误在于您访问元组键中的项目的方式。他们是他的财产。

所以,如果你试图把它变成文字这是一种:"Item in dictionary(KeyValuePair<>).Key.(Key is a tuple with 5 fields - so select property of that field)"

在结束 - 寻找最适合自己要求的项目后,你回来了IEnumerable<KeyValuePair<>>所以当你Sum你应该指定什么 - 在这个例子中是Value

double TOTAL = dctMC.Where(Z => listIDs.Contains(Z.Key.Item1) && 
           Z.Key.Item2 == "Apple" && 
           Z.Key.Item4 == 9 && 
           Z.Key.Item5 == "Green") 
        .Sum(item => item.Value); 

**另请注意,你不小心用Item3 == 9代替Item4和同样与Item4 == "Green"代替Item5 *


不知道如果这是问题或没有,但着想我建议远离这样的Tuples,只是把它放在一个合适的定义类(或匿名类型,如果它来自其他查询)

+0

感谢您的帮助 - 我正在运行一个大型的模拟,我试图分析和存储结果在字典之前添加他们使用循环访问键/值对来回到数据表。如果有更好的方法可以做到这一点,请你指点一下正确的方向吗?我决定使用一个元组而不是嵌套字典。 – Zeus

+0

这是处理分层数据的更好方法吗? (http://stackoverflow.com/questions/24708236/c-sharp-nested-dictionary-better-alternative-best-organize-data-across-three-c) – Zeus

+0

@Zeus - 没有看到它的细节,但如果它是用一个类替换5个字段的Tuple - 答案是肯定的:) –

2

当你迭代字典,元素是KeyValuePair<>实例。您需要Select值来概括他们:

double TOTAL = dctMC.Where(Z => 
         lstIDs.Contains(Z.Key.Item1)) && 
         Z.Key.Item2 == "Apple" && 
         Z.Key.Item4 == 9 && Z.Key.Item5 == "Green") 
        .Select(Z => Z.Value) 
        .Sum(); 

或使用Sum()超载与选择的λ是这样的:

double TOTAL = dctMC.Where(Z => 
         lstIDs.Contains(Z.Key.Item1)) && 
         Z.Key.Item2 == "Apple" && 
         Z.Key.Item4 == 9 && Z.Key.Item5 == "Green") 
        .Sum(Z => Z.Value); 

注意,在一个Tuple<>项目像tuple.Item1tuple.Item2等访问,不是tuple(item1)

+0

这不会编译 - 'Item3'是一个字符串,'Item4'是int –

+0

@GiladGreen thx,编辑时必须以某种方式混合索引... –

+0

不是你的错误 - 这是他的原代码中的错误: ) –

2

这是比较容易,如果你打破它为多个阶段,来包装你的头周围:
首先过滤掉不相关的项目(通过键),然后求和值:

var filtered = //This is an IEnumerable of KeyValuePair<Tuple<int, string, string, int, string>, double> 
    dctMC.Where(Z => listIDs.Contains(Z.Key.Item1) && 
             Z.Key.Item2 == "Apple" && 
             Z.Key.Item4 == 9 && 
             Z.Key.Item5 == "Green") 
var values = filtered.Select(item => item.Value); //the doubles you want to sum 
double TOTAL = values.Sum();       //The sum you were looking for... 
+0

感谢所有的帮助!!,我已经得到了代码工作,但按照Gilad Green;上面的评论可能是更好的方法。 – Zeus