【问题标题】:How to combine different values of IEnumerable? [duplicate]如何组合 IEnumerable 的不同值? [复制]
【发布时间】:2021-07-04 19:59:42
【问题描述】:

在这个概念上苦苦挣扎:我有一个返回 IEnumerable 的方法,如下所示:

public IEnumerable<IFruit> FruitStall(IEnumerable<IFruit> fruits)... 

每个IFruit如下

public decimal Amount { get; }
public string Code { get; }

我的FruitsStall 方法为每种货币返回一个IFruit,其中包含相同代码的所有货币的总和。

例如

{APL10, APL20, APL50} => {APLE80}
or
{APL10, APL20, ORG50} => {APL30, ORG50}

谁能指出我正确的方向?不太清楚该怎么做。

我正在循环使用 IEnumerable

foreach (var item in fruits)
{
    fruits.Code
}

但不确定去哪里

【问题讨论】:

  • 无法理解你想要什么;你开始描述你的方法已经做了什么,然后你问是否有人可以帮忙。帮忙做什么?如果你的方法已经做了 X 那么还有什么可以帮助你呢?顺便说一句,尽量使方法名称成为动词而不是名词。

标签: c# iteration ienumerable


【解决方案1】:

当你说:

{APL10, APL20, APL50} => {APLE80}
or
{APL10, APL20, ORG50} => {APL30, ORG50}

如果你的意思是

我有这个:{new Fruit("APL",10), new Fruit("APL", 20), new Fruit("ORG",50)},我想生成一个类似{new Fruit("APL",30), new Fruit("ORG",50)}的列表

我会说:

您需要有一些容器来容纳所有不同的代码并将它们映射到 Amounts 的总和。为此,我们经常使用字典:

var d = new Dictionary<string,decimal>();
foreach(var f in fruit){
  if(!d.ContainsKey(f.Code))
    d[f.Code] = f.Amount;
  else
    d[f.Code] += f.Amount;
}

在此操作结束时,您的字典将包含一组唯一的水果代码和所有数量的总和。您可以通过枚举字典并以与最初创建列表类似的方式创建列表来将其重新转换为水果列表

一旦你明白了这一点,你就可以看看如何使用 LINQ,然后执行以下操作:

var summedFruits = fruits
  .GroupBy(f => f.Code)
  .Select(g => new Fruit(g.Key, g.Sum(f => f.Amount)));

(这假设你的 Fruit 有一个构造函数,它接受一个代码和一个数量)。当您在 LINQ 中进行 GroupBy 时,您会得到一个类似于列表列表的输出。原始输入列表被分解成一些列表;每个列表中的所有内容都具有与您声明的键相同的值(我说按代码分组)

所以你的原始表示:

{APL10, APL20, ORG50}

最终看起来像:

Key = APL, List = {APL10, APL20}
Key = ORG, List = {ORG50}

你的“一个三样东西的列表”已经变成了“一个(两个 APL 的列表)和(一个 ORG 的列表)的列表”

如果您随后在它们上运行选择,您可以创建一个新 Fruit,它使用 Key 作为代码并总结每个列表中的数量

Key = APL, List = {APL10, APL20}, Sum = 30
Key = ORG, List = {ORG50}, Sum = 50

在这段代码中:

var summedFruits = fruits
  .GroupBy(f => f.Code)
  .Select(g => new Fruit(g.Key, g.Sum(f2=> f2.Amount)));

f 是一个水果,是原始列表中的 3 个水果之一。我们按水果的代码分组。 g是分组操作的结果,是一个“有共同代码的水果列表”,Key是代码(apl或org)。 g 是一个列表,所以你可以调用 sum 。 g 列表中的每个项目都是一个水果,这就是为什么我切换回f(当我说 f2 时),以帮助记住它是一个单独的水果——我们正在对数量求和。对于 APL 的第一个列表,总和为 30。在操作结束时,会产生一个新列表;一个有两个元素 - APL 和 ORG,但数量是所有元素的总和

【讨论】:

  • 顺便说一句,您不需要 .Select (并枚举​​两次)。分组时也可以完成总结:var summedFruits = fruits.GroupBy(f =&gt; f.Code, (k, fs) =&gt; new Fruit(k, fs.Sum(f=&gt; f.Amount)));
  • 我不确定您评论的所有部分是否正确,但我同意您的建议是所发布代码的精简版。无论如何,我出于教育原因打破了它;我已经认为 LINQ 解决方案是一座过分的桥梁,而不是想打高尔夫球
【解决方案2】:
var res = fruits.GroupBy(x => x.Code).ToDictionary(g => g.Key, g => g.Sum(x => x.Amount));

【讨论】:

  • 感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将有助于未来的读者更好地了解正在发生的事情,尤其是那些刚接触该语言并难以理解概念的社区成员。
猜你喜欢
  • 1970-01-01
  • 2011-07-25
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多