【问题标题】:Filter then sum dictionary with tuple as key过滤然后以元组为键对字典求和
【发布时间】:2016-12-08 23:03:34
【问题描述】:

我正在尝试过滤然后以元组为键对字典求和。 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()

【问题讨论】:

  • 非常适合添加带有值的初始化代码 - 让您更容易理解问题并帮助您解决问题 :)

标签: c# dictionary filter tuples


【解决方案1】:

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

因此,如果您尝试将其表达为:"Item in dictionary(KeyValuePair&lt;&gt;).Key.(Key is a tuple with 5 fields - so select property of that field)"

最后 - 在找到符合您要求的项目后,您会返回 IEnumerable&lt;KeyValuePair&lt;&gt;&gt;,所以当您 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,只需将其放入适当定义的类(或匿名类型,如果它来自其他一些查询)

【讨论】:

  • 感谢您的帮助 - 我正在运行一个大型模拟,我正在尝试分析结果并将其存储在字典中,然后使用循环将它们添加回数据表以访问键/值一对。如果有更好的方法,请您指出正确的方向吗?我决定使用元组而不是嵌套字典。
  • 这是处理分层数据的更好方法吗? (stackoverflow.com/questions/24708236/…)
  • @Zeus - 没有详细查看它,但如果它用 5 个字段和一个类替换元组 - 答案是肯定的 :)
  • 谢谢你知道我可以学习如何完成的任何链接吗?我必须使用分层结构,否则班级将有 5000 个项目...
  • 5000 个属性?那么我认为你有一些设计问题......只是一般地阅读有关如何正确划分类等的内容。如果你真的有一个有 5000 个字段的类.....也许使用动态 - 但我仍然会说存在设计问题..
【解决方案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...

【讨论】:

  • 感谢所有的帮助!!,我的代码可以工作了,但是根据 Gilad Green 的评论,上面可能有更好的方法。
【解决方案3】:

当您遍历字典时,元素是 KeyValuePair&lt;&gt; 实例。您需要 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() 重载与选择器 lambda 一起使用,如下所示:

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&lt;&gt; 中的项目的访问方式类似于 tuple.Item1tuple.Item2 等,而不是 tuple(item1)

【讨论】:

  • 这不会编译 - Item3 是一个字符串,Item4 是 int
  • @GiladGreen thx,一定是在编辑时混淆了索引...
  • 不是你的错误 - 这是他原始代码中的错误:)
猜你喜欢
  • 1970-01-01
  • 2016-01-10
  • 2021-07-30
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 1970-01-01
  • 2022-12-15
相关资源
最近更新 更多