C# 即使两个列表中都不存在项目,如何获取两个列表中的所有项目?

C# 即使两个列表中都不存在项目,如何获取两个列表中的所有项目?,c#,.net,linq,C#,.net,Linq,我有两个可列举的清单 List<List_Data> List1 = new List<List_Data>(); List1.Add(new List_Data { Material = "1", Batch = "B1", QTY = 5 }); List1.Add(new List_Data { Material = "1", Batch = "B2", QTY = 5 }); List1.Add(new List_Data { Material = "2", Ba

我有两个可列举的清单

List<List_Data> List1 = new List<List_Data>();
List1.Add(new List_Data { Material = "1", Batch = "B1", QTY = 5 });
List1.Add(new List_Data { Material = "1", Batch = "B2", QTY = 5 });
List1.Add(new List_Data { Material = "2", Batch = "B1", QTY = 15 });

List<List_Data> List2 = new List<List_Data>();
List2.Add(new List_Data { Material = "1", Batch = "B1", QTY = 2 });
List2.Add(new List_Data { Material = "3", Batch = "B1", QTY = 5 });
List2.Add(new List_Data { Material = "3", Batch = "B2", QTY = 15 });
这就是我到目前为止所做的

SendList = (from l1 in List1
            join l2 in List2 on new { l1.Material, l1.Batch } equals new { l2.Material, l2.Batch } into temp
            from l2 in temp.DefaultIfEmpty()
            select new Report_Class
            {
                Material = l1.Material != null ? l1.Material : l2.Material, 
                Batch = l1.Batch != null ? l1.Batch : l2.Batch, 
                Difference = l1 != null && l2 != null ? (l1.QTY - l2.QTY).ToString() : l1 != null ? l1.QTY.ToString() : l2.QTY.ToString(), 

            }).ToList();
问题是它返回列表1所有存在的项,但不返回仅存在于列表2中的项。任何帮助都将不胜感激


谢谢

如果我们假设第二个列表中最多有一个元素(如果有的话)具有相同的
材料
Bacth
值,那么简单的解决方案可能是:

// Initially project each element in the list to an element that 
// has also the info in which list this item is contained.
var list1 = List1.Select(x => new {Data = x, List = 1});
var list2 = List2.Select(x => new {Data = x, List = 2});

var result = list1.Concat(list2)
            .GroupBy(x => new {x.Data.Batch, x.Data.Material})
            .Select(gr =>
            {
                var itemsInGroup = gr.Count();
                if (itemsInGroup == 1)
                {
                    var onlyItemInGroup = gr.First();

                    if (onlyItemInGroup.List == 1)
                    {
                        return onlyItemInGroup.Data;
                    }

                    // Item came from the second list. So multiply it's quantity by -1.
                    onlyItemInGroup.Data.QTY *= -1;

                    return onlyItemInGroup.Data;
                }

                // Since for each item in list 1 there is at most one item in the list2
                // and vice versa itemsInGroup now is 2 and it is safe to use First as below
                // to grab the items.

                var itemFromFirstList = gr.First(x => x.List == 1);
                var itemFromSecondList = gr.First(x => x.List == 2);

                return new List_Data
                {
                    Material = gr.Key.Material,
                    Batch = gr.Key.Batch,
                    QTY = itemFromFirstList.Data.QTY - itemFromSecondList.Data.QTY
                };
            }).ToList();
基本上,所有工作都是在将两个列表连接起来并根据键
物料
批次
将结果列表中的项目分组后,在
选择
中完成的。我们基于最初假设的选项如下:

// Initially project each element in the list to an element that 
// has also the info in which list this item is contained.
var list1 = List1.Select(x => new {Data = x, List = 1});
var list2 = List2.Select(x => new {Data = x, List = 2});

var result = list1.Concat(list2)
            .GroupBy(x => new {x.Data.Batch, x.Data.Material})
            .Select(gr =>
            {
                var itemsInGroup = gr.Count();
                if (itemsInGroup == 1)
                {
                    var onlyItemInGroup = gr.First();

                    if (onlyItemInGroup.List == 1)
                    {
                        return onlyItemInGroup.Data;
                    }

                    // Item came from the second list. So multiply it's quantity by -1.
                    onlyItemInGroup.Data.QTY *= -1;

                    return onlyItemInGroup.Data;
                }

                // Since for each item in list 1 there is at most one item in the list2
                // and vice versa itemsInGroup now is 2 and it is safe to use First as below
                // to grab the items.

                var itemFromFirstList = gr.First(x => x.List == 1);
                var itemFromSecondList = gr.First(x => x.List == 2);

                return new List_Data
                {
                    Material = gr.Key.Material,
                    Batch = gr.Key.Batch,
                    QTY = itemFromFirstList.Data.QTY - itemFromSecondList.Data.QTY
                };
            }).ToList();
  • 该组仅包含一个项目,该项目来自第一个列表。在本例中,我们只返回此项包含的数据
  • 该组仅包含一个项目,该项目来自第二个列表。在这种情况下,我们必须将值
    QTY
    乘以-1。请记住,要使用的类型是
    list1.QTY-list2.QTY
    ,并且在第一个列表
    list1
    中没有任何关联的元素。因此,您希望获得声明的
    -list2.QTY
  • 该组包含两个项目,因为我们假设一个列表中最多(如果有的话)有一个关联元素,而另一个列表中的另一个元素则有一个关联元素。在这种情况下,我们只需从
    list1.QTY
    中减去
    list2.QTY
    ,即可得到新的数量

如果我们假设第二个列表中最多(如果有的话)有一个元素具有相同的
材料
Bacth
值,那么简单的解决方案可能是:

// Initially project each element in the list to an element that 
// has also the info in which list this item is contained.
var list1 = List1.Select(x => new {Data = x, List = 1});
var list2 = List2.Select(x => new {Data = x, List = 2});

var result = list1.Concat(list2)
            .GroupBy(x => new {x.Data.Batch, x.Data.Material})
            .Select(gr =>
            {
                var itemsInGroup = gr.Count();
                if (itemsInGroup == 1)
                {
                    var onlyItemInGroup = gr.First();

                    if (onlyItemInGroup.List == 1)
                    {
                        return onlyItemInGroup.Data;
                    }

                    // Item came from the second list. So multiply it's quantity by -1.
                    onlyItemInGroup.Data.QTY *= -1;

                    return onlyItemInGroup.Data;
                }

                // Since for each item in list 1 there is at most one item in the list2
                // and vice versa itemsInGroup now is 2 and it is safe to use First as below
                // to grab the items.

                var itemFromFirstList = gr.First(x => x.List == 1);
                var itemFromSecondList = gr.First(x => x.List == 2);

                return new List_Data
                {
                    Material = gr.Key.Material,
                    Batch = gr.Key.Batch,
                    QTY = itemFromFirstList.Data.QTY - itemFromSecondList.Data.QTY
                };
            }).ToList();
基本上,所有工作都是在将两个列表连接起来并根据键
物料
批次
将结果列表中的项目分组后,在
选择
中完成的。我们基于最初假设的选项如下:

// Initially project each element in the list to an element that 
// has also the info in which list this item is contained.
var list1 = List1.Select(x => new {Data = x, List = 1});
var list2 = List2.Select(x => new {Data = x, List = 2});

var result = list1.Concat(list2)
            .GroupBy(x => new {x.Data.Batch, x.Data.Material})
            .Select(gr =>
            {
                var itemsInGroup = gr.Count();
                if (itemsInGroup == 1)
                {
                    var onlyItemInGroup = gr.First();

                    if (onlyItemInGroup.List == 1)
                    {
                        return onlyItemInGroup.Data;
                    }

                    // Item came from the second list. So multiply it's quantity by -1.
                    onlyItemInGroup.Data.QTY *= -1;

                    return onlyItemInGroup.Data;
                }

                // Since for each item in list 1 there is at most one item in the list2
                // and vice versa itemsInGroup now is 2 and it is safe to use First as below
                // to grab the items.

                var itemFromFirstList = gr.First(x => x.List == 1);
                var itemFromSecondList = gr.First(x => x.List == 2);

                return new List_Data
                {
                    Material = gr.Key.Material,
                    Batch = gr.Key.Batch,
                    QTY = itemFromFirstList.Data.QTY - itemFromSecondList.Data.QTY
                };
            }).ToList();
  • 该组仅包含一个项目,该项目来自第一个列表。在本例中,我们只返回此项包含的数据
  • 该组仅包含一个项目,该项目来自第二个列表。在这种情况下,我们必须将值
    QTY
    乘以-1。请记住,要使用的类型是
    list1.QTY-list2.QTY
    ,并且在第一个列表
    list1
    中没有任何关联的元素。因此,您希望获得声明的
    -list2.QTY
  • 该组包含两个项目,因为我们假设一个列表中最多(如果有的话)有一个关联元素,而另一个列表中的另一个元素则有一个关联元素。在这种情况下,我们只需从
    list1.QTY
    中减去
    list2.QTY
    ,即可得到新的数量
    • 这里有一种方法:

      • 反转列表2上的
        QTY
      • 将上述结果与列表1连接起来
      • 物料
        批次
        对串联列表进行分组,并汇总
        数量
      下面是代码:

      var result = List1.Concat(
                   List2.Select(list2Item => new List_Data
                   {
                       Material = list2Item.Material,
                       Batch = list2Item.Batch,
                       QTY = list2Item.QTY * -1
                   }))
                   .GroupBy(item => new { item.Material, item.Batch })
                   .Select(grouped => new List_Data
                   {
                       Material = grouped.First().Material,
                       Batch = grouped.First().Batch,
                       QTY = grouped.Sum(item => item.QTY)
                   })
                   .ToList();
      
      即使您有空的
      数量
      ,它仍然可以工作。例如,具有以下值:

      List<List_Data> List1 = new List<List_Data>();
      List1.Add(new List_Data { Material = "1", Batch = "B1", QTY = 5 });
      List1.Add(new List_Data { Material = "1", Batch = "B2", QTY = 5 });
      List1.Add(new List_Data { Material = "2", Batch = "B1", QTY = 15 });
      List1.Add(new List_Data { Material = "3", Batch = "B1", QTY = null });
      List1.Add(new List_Data { Material = "3", Batch = "B3", QTY = 4 });
      
      List<List_Data> List2 = new List<List_Data>();
      List2.Add(new List_Data { Material = "1", Batch = "B1", QTY = 2 });
      List2.Add(new List_Data { Material = "3", Batch = "B1", QTY = 5 });
      List2.Add(new List_Data { Material = "3", Batch = "B2", QTY = 15 });
      List2.Add(new List_Data { Material = "3", Batch = "B3", QTY = null });
      
      这里有一种方法:

      • 反转列表2上的
        QTY
      • 将上述结果与列表1连接起来
      • 物料
        批次
        对串联列表进行分组,并汇总
        数量
      下面是代码:

      var result = List1.Concat(
                   List2.Select(list2Item => new List_Data
                   {
                       Material = list2Item.Material,
                       Batch = list2Item.Batch,
                       QTY = list2Item.QTY * -1
                   }))
                   .GroupBy(item => new { item.Material, item.Batch })
                   .Select(grouped => new List_Data
                   {
                       Material = grouped.First().Material,
                       Batch = grouped.First().Batch,
                       QTY = grouped.Sum(item => item.QTY)
                   })
                   .ToList();
      
      即使您有空的
      数量
      ,它仍然可以工作。例如,具有以下值:

      List<List_Data> List1 = new List<List_Data>();
      List1.Add(new List_Data { Material = "1", Batch = "B1", QTY = 5 });
      List1.Add(new List_Data { Material = "1", Batch = "B2", QTY = 5 });
      List1.Add(new List_Data { Material = "2", Batch = "B1", QTY = 15 });
      List1.Add(new List_Data { Material = "3", Batch = "B1", QTY = null });
      List1.Add(new List_Data { Material = "3", Batch = "B3", QTY = 4 });
      
      List<List_Data> List2 = new List<List_Data>();
      List2.Add(new List_Data { Material = "1", Batch = "B1", QTY = 2 });
      List2.Add(new List_Data { Material = "3", Batch = "B1", QTY = 5 });
      List2.Add(new List_Data { Material = "3", Batch = "B2", QTY = 15 });
      List2.Add(new List_Data { Material = "3", Batch = "B3", QTY = null });
      
      这里是另一个解决方案

      var result = List1
          .Select(e => new        
          {
              key = new
              {
                  e.Material, 
                  e.Batch
              }, 
              QTY = e.QTY
          })
          .Concat(List2
              .Select(e => new
              {
                  key = new
                  {
                      e.Material, 
                      e.Batch
                  }, 
                  QTY = -e.QTY
              }))
          .GroupBy( e => e.key, e => e.QTY )
          .Select(g => new Report_Class
          {
              Material = g.Key.Material, 
              Batch = g.Key.Batch, 
              Difference = g.Sum()
          })
          .ToList();
      
      这里是另一个解决方案

      var result = List1
          .Select(e => new        
          {
              key = new
              {
                  e.Material, 
                  e.Batch
              }, 
              QTY = e.QTY
          })
          .Concat(List2
              .Select(e => new
              {
                  key = new
                  {
                      e.Material, 
                      e.Batch
                  }, 
                  QTY = -e.QTY
              }))
          .GroupBy( e => e.key, e => e.QTY )
          .Select(g => new Report_Class
          {
              Material = g.Key.Material, 
              Batch = g.Key.Batch, 
              Difference = g.Sum()
          })
          .ToList();
      

      您需要Concat、GroupBy和SelectTypo:您的输出显示
      quaty
      ,但您的select语句有
      差异
      。此外,最好使用比
      List1
      List2
      更有意义的变量名。您需要Concat、GroupBy和SelectTypo:您的输出显示
      QTY
      ,但select语句有
      差异。另外,最好使用比
      List1
      List2
      更有意义的变量名。您好,感谢您回答这个问题,但是我在“item.Data.QTY*=-1;”中遇到了一个错误,属性或索引器“AnonymousType#1.QTY”无法分配给--它是只读的。@DinukshiJayarathne欢迎您。嗯……我执行了代码,但没有发现这个问题。顺便说一下,在初始化
      List2
      之后,您必须使用
      List2.Add
      而不是
      List1.Add
      。请纠正这一点,让我知道。谢谢,谢谢你回答这个问题,但是我在'item.Data.QTY*=-1;'中遇到一个错误,属性或索引器“AnonymousType#1.QTY”无法分配给--它是只读的。@DinukshiJayarathne欢迎您。嗯……我执行了代码,但没有发现这个问题。顺便说一下,在初始化
      List2
      之后,您必须使用
      List2.Add
      而不是
      List1.Add
      。请纠正这一点,让我知道。谢谢你。感谢you@FrankFajardo我提供了非常好的解决方案(+1)。谢谢@Christos。我很感激。:)是的。感谢you@FrankFajardo我提供了非常好的解决方案(+1)。谢谢@Christos。我很感激。:)