2016-04-27 21 views
3

我只是想知道是否有一種方法來鞏固與LINQ訂單對象列表?我的情景是我爲了這個問題而壓縮的以下內容。與Linq合併清單<T>?

public class Order 
{ 
    public string Guid { get; set; } 
    public string Parent { get; set; } 
    public string ProductID { get; set; } 
    public string Description { get; set; } 
    public double Quantity { get; set; } 
    public double Total { get; set; } 
} 

這將成爲基於上述列表如下:

GUID  PARENT  ID   Desc   Qty   Total 
==================================================================== 
aaa      120  Burger   1   2.50 
bbb  aaa   121  + Bacon  1   0.50 
ccc      123  Fries   1   1.50 
ddd      120  Burger   1   2.50 
eee  ddd   124  + Cheese  1   0.30 
fff      123  Fries   1   1.50 

什麼,我想在這個例子中做的是與以下

GUID  PARENT  ID   Desc   Qty   Total 
==================================================================== 
aaa      120  Burger   1   2.50 
bbb  aaa   121  + Bacon  1   0.50 
ccc      123  Fries   2   3.00 
ddd      120  Burger   1   2.50 
eee  ddd   124  + Cheese  1   0.30 

在哪裏結束如果商品有兒童產品,我不會嘗試合併,基本上總計其他商品的總數和數量。

我現在的想法是創建一個單獨的沒有孩子的產品清單總結這一點,並與有孩子的產品進行精細合併。

我能做到這樣,但我不知道是否有一個更簡潔的方法,任何輸入將不勝appreaciated

+0

尋找Concat? https://msdn.microsoft.com/zh-cn/library/bb386979(v=vs.100).aspx –

+1

爲什麼添加項目時不添加數量?首先檢查該項目是否已經在該列表中,如果是這樣,則將+1添加到數量中。 – Spluf

+2

我同意@Spluf - 這不是您的數據的最佳模式。這不是訂單 - 這是訂單*項目*。列表是順序,但它聽起來像沒有提供給你所需數據的界面。 – Conduit

回答

3

這應該保持訂單與孩子分開,鞏固只有單機單:

var orders = originalOrders.GroupBy(_ => _.parent ? _.parent : _.guid); 
var consolidated = orders 
    .Where(grp => grp.Count() == 1) // only orders with no children 
    .SelectMany(grp => grp) 
    .GroupBy(_ => _.ID) 
    .Select(grp => grp.Aggregate((a,b) => new order 
     { 
      guid = a.guid, 
      parent = a.parent, 
      ProductID = a.ProductID, 
      Description = a.Description, 
      Quantity = a.Quantity + b.Quantity, 
      Total = a.Total + b.Total 
     } 
)); 

var allOrders = orders 
    .Where(grp => grp.Count() > 1) 
    .SelectMany(grp => grp) 
    .Concat(consolidated); 
+1

這看起來不錯,但我想你錯過了一個條件:'不要嘗試鞏固,如果該項目有一個兒童產品' –

+0

Ooops是好點! OP應該決定如何處理這種情況,例如一個漢堡配培根和一個芝士漢堡,應該顯示爲2個漢堡,1個培根,1個奶酪?如果在訂單類別 – Mike

+0

上有孩子的參考,這將有所幫助,我不會將它作爲2xburger 1培根1奶酪進行整合,因爲它很難知道哪個人擁有哪個或哪個漢堡包都具有這兩個特點 - 鞏固任何與兒童產品 - 複雜的我知道! – JazziJeff

1
from o in orders 
group o by o.ID into g 
from gg in g select new Order 
{ 
     guid = gg.guid, parent = gg.parent, ProductId = gg.ProductId, Description = gg.Description, 
     Quantity = orders.Any(od=> od.parent != null || od.parent == gg.guid) 
         ? gg.Quantity : g.Sum(ggg=>ggg.Quantity), 
     Total = orders.Any(od=> od.parent != null || od.parent == gg.guid) 
         ? gg.Total : g.Sum(ggg=>ggg.Total) 
} 

這可能會有一些性能問題,但這應該讓你開始。

+0

謝謝,我似乎遇到了一個問題,從gg中選擇新的Order請參閱https://dotnetfiddle.net/S6WhNW,如果得到一個機會 – JazziJeff

+0

@JazziJeff,更新 –

2

如果你想一次做到這一點,關鍵是計算一些東西來分組。 由於我們不想將子項目與子項目進行分組,因此我們需要一些獨特的項目進行分組。如果我們拿兩個漢堡包,唯一不同的是Guid,所以這需要在我們的分組中。如果該項目沒有子行,我們應該對它們進行分組。 所以我們計算一個組合子句,如果該項目有子項,則成爲Guid,如果項目沒有子項,則成爲空字符串。 然後ProductID也需要分組,因爲這是我們想要將沒有孩子的項目分組的項目。

var lst = orders.GroupBy(x => new 
{ 
    x.ProductID, 
    GuidIfHaveChildren = (orders.Any(x2 => x2.Parent == x.Guid) ? x.Guid : ""), 
    x.parent 
}).Select(x => new 
{ 
    Guid = x.First().Guid, 
    Parent = x.First().Parent, 
    Id = x.Key.ProductID, 
    Desc = x.First().Description, 
    Qty = x.Sum(p => p.Quantity), 
    Total = x.Sum(p => p.Total) 
}); 
+0

非常接近,但它似乎分組的兒童產品對父母。例如,如果我賣1個漢堡+培根,2個薯條,1個漢堡加培根,輸出是1x漢堡+ 2xbacon,2xfries,1x漢堡 - 理想情況下它應該保持與每個漢堡的培根,如果有意義 – JazziJeff

+0

你能否更新示例數據包括這種情況?所以我說得對。 – fhogberg

+0

https://dotnetfiddle.net/S6WhNW - 快速擺弄你的答案只是爲了測試,謝謝 – JazziJeff