【问题标题】:Difference between two lists with linq两个带有 linq 的列表之间的区别
【发布时间】:2019-06-29 00:33:59
【问题描述】:

我有两个包含两个字段的列表。我事先不知道哪个更大。

我想实现这个:

        newList              oldList
Fruit       Qty     Diff    Fruit       Qty
--------------------------------------------
apple       3       +1      apple       2
                    -2      pear        2
peach       4       +3      peach       1
melon       5        0      melon       5
coconut     2       +2      
mango       4        0      mango       4
banana      2       -1      banana      3
lychi       1       +1      
                    -3      pineapple   3

左边一个你可以在右边看到newList oldList。如果我将 oldList 与 newList 进行比较,我想查看每个可能的行以及两个列表之间的 Quantity 差异。

我写了这个,它会给我两个列表中都不包含的水果(xor)

var difference = newList.Select(x => x.Fruit)
                        .Except(oldList.Select(x => x.Fruit))
                        .ToList()
                        .Union(oldList.Select(x => x.Fruit)
                        .Except(newList.Select(x => x.Fruit))
                        .ToList());

但我也不知道如何将它与 Qty 结合起来。

【问题讨论】:

  • 这似乎是使用普通的foreach 然后在该循​​环中使用简单的LINQ。这些真的是清单吗?还是它们实际上是字典?
  • 你的Fruit是一个班级吗?如果是这样,请将其添加到您的问题中。
  • 这些列表是来自数据库的 linq 查询的结果,我只取了两列,水果和数量。所以 Fruit 是一个字段。

标签: c# linq list


【解决方案1】:

我没有看到一种使用 LINQ 的方法可以很好地执行并且还具有可读性。我更喜欢混合使用 LINQ 和循环:

var oldGrouped = oldList.ToDictionary(x => x.Fruit, x => x.Qty);
var newGrouped = newList.ToDictionary(x => x.Fruit, x => x.Qty);

var result = new List<FruitSummary>();

foreach(var oldItem in oldGrouped)
{
    var summary = new FruitSummary { OldFruit = oldItem.Key, OldQty = oldItem.Value };
    if(newGrouped.TryGetValue(oldItem.Key, out int newQuantity) && newQuantity != 0)
    {
        summary.NewFruit = oldItem.Key;
        summary.NewQty = newQuantity;
    }
    summary.Diff = oldItem.Value - newQuantity;
    newGrouped.Remove(oldItem.Key);
    result.Add(summary);
}

foreach(var newItem in newGrouped)
{
    result.Add(new FruitSummary { Diff = -newItem.Value,
                                  NewFruit = newItem.Key,
                                  NewQty = newItem.Value });
}

FruitSummary 类如下所示:

public class FruitSummary
{
    public string OldFruit { get; set; }
    public string NewFruit { get; set; }
    public int OldQty { get; set; }
    public int NewQty { get; set; }
    public int Diff { get; set; }
}

【讨论】:

    【解决方案2】:

    我假设你有一个像这样的Fruit 类:

    public class Fruit
    {
        public string Name {get; set;}
        public int Quantity {get; set;}
    }
    

    你有一个像这样的新旧列表

    List<Fruit> oldList = ...
    List<Fruit> newList = ...
    

    那么这个 LINQ 怪物就可以了,虽然它可能不是最高效的解决方案(但是有多少种水果呢?):

    var result = 
        oldList.Join(newList, 
            oldFruit => oldFruit.Name,
            newFruit => newFruit.Name,
            (oldFruit, newFruit) => new {
                Name = oldFruit.Name,
                Diff = oldFruit.Quantity - newFruit.Quantity}).
        Concat(oldList.
            Where(oldFruit => newList.All(newFruit => newFruit.Name != oldFruit.Name)).
            Select(oldFruit => new {
                Name = oldFruit.Name,
                Diff = -oldFruit.Quantity})).
        Concat(newList.Where(newFruit => oldList.All(oldFruit => oldFruit.Name != newFruit.Name)).
            Select(newFruit => new {
                Name = newFruit.Name,
                Diff = newFruit.Quantity}));
    

    你可以像这样输出结果:

    Console.WriteLine(string.Join(Environment.NewLine, result.Select(r => $"{r.Name} {r.Diff}")));
    

    请注意,我提出这个是因为我喜欢 linq “one liner”,但使用 foreach 似乎比这个查询更具可读性,甚至可能更快。

    【讨论】:

      【解决方案3】:

      这样的?

      var difference = newList
          .Concat(oldList.Select(x => new { x.Fruit, Qty = -x.Qty }))
          .GroupBy(x => x.Fruit)
          .Select(g => new {Fruit = g.Key, Qty = g.Sum(x => x.Qty) });
      

      当我运行foreach(var d in difference) Console.WriteLine(d); 时,我得到:

      { Fruit = apple, Qty = 1 }
      { Fruit = peach, Qty = 3 }
      { Fruit = melon, Qty = 0 }
      { Fruit = coconut, Qty = 2 }
      { Fruit = mango, Qty = 0 }
      { Fruit = banana, Qty = -1 }
      { Fruit = lychi, Qty = 1 }
      { Fruit = pear, Qty = -2 }
      { Fruit = pineapple, Qty = -3 }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-06
        • 2014-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-25
        相关资源
        最近更新 更多