簡體   English   中英

即使兩個列表中都不存在項目,如何獲取兩個列表中的所有項目?

[英]How to get all the items in both lists even when items not existing in both lists?

我有兩個清單。

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 });

我想要的是比較兩個列表,並根據物料和批次獲得差異QTY(list1.QTY-list2.QTY)。 即使其他清單上不存在某項,我也需要根據該物料和批次減去或增加數量。

這是我期望的結果。

Material = "1", Batch = "B1", QTY = 3
Material = "1", Batch = "B2", QTY = 5 
Material = "2", Batch = "B1", QTY = 15
Material = "3", Batch = "B1", QTY = -5
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();

問題是它返回list1所存在的所有項目,但不返回僅存在於list 2中的項目。將不勝感激。

謝謝。

這是一種方法:

  • 反轉List2上的QTY
  • 將上述結果與List1連接。
  • 按“ Material和“ Batch對串聯列表進行分組,並匯總QTY

它在代碼中:

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();

即使您的QTY空,它仍然可以使用。 例如,具有以下值:

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 });

將導致:

Material: "1", Batch: "B1", QTY: 3
Material: "1", Batch: "B2", QTY: 5
Material: "2", Batch: "B1", QTY: 15
Material: "3", Batch: "B1", QTY: -5
Material: "3", Batch: "B3", QTY: 4
Material: "3", Batch: "B2", QTY: -15

如果我們假設在第二個列表中最多(如果有的話)一個元素具有相同的MaterialBacth值,那么一個簡單的解決方案可能是:

// 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();

基本上,在我們將兩個列表連接在一起並根據關鍵的MaterialBatch將結果列表中的項目分組之后,所有工作都在Select內部完成。 根據最初的假設,我們有以下幾種選擇:

  • 該組僅包含一個項目,該項目來自第一個列表。 在這種情況下,我們只返回該項目包含的數據。
  • 該組僅包含一個項目,該項目來自第二個列表。 在這種情況下,我們必須將值QTY乘以-1。 請記住,您要使用的類型是list1.QTY - list2.QTY並且第一個列表list1沒有任何關聯的元素。 因此,您想要獲取已聲明的-list2.QTY
  • 該組包含兩個項目,並且由於我們假設一個列表中最多有一個關聯元素(如果有),而另一個列表中則有另一個元素。 在這種情況下,我們剛剛減去list2.QTYlist1.QTY來獲得新的數量。

這是另一種解決方案

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();

.net小提琴樣本

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM