2009-06-09 63 views
4

是否可以使用.NET的LINQ對分層數據進行求和?使用LINQ的分層數據總和?

我的數據類看起來是這樣的:

class Node 
{ 
    public decimal Amount; 
    public IEnumerable<Node> Children { get; set; } 
} 

所以我有一些數據看起來是這樣,但當然,樹可以有任意的深度。

var amounts = new Node 
{ 
    Amount = 10; 
    Children = new[] 
    { 
     new Node 
     { 
      Amount = 20 
     }, 
     new Node 
     { 
      Amount = 30 
     } 
    } 
}; 

這是可能的總和所有的金額,並得到60一個簡單的LINQ查詢結果?

回答

2
:選項:)

第一種形式的全部例子很多

技術上你可以write recursive lambda expressions,但你需要瘋狂或瘋狂明亮的嘗試(我還沒有想出哪個)。但你可以作弊:

Func<Node, decimal> nodeSum = null; 
    nodeSum = node => { 
     decimal result = node.Amount; 
     if (node.Children != null) { 
      result = result + node.Children.Sum(nodeSum); 
     } 
     return result; 
    }; 
    var value = nodeSum(amounts); 
15

您可以用高階函數做:

Func<Node, decimal> summer = null; 
summer = node => node.Amount + 
       (node.Children == null ? 0m : node.Children.Sum(summer)); 
decimal total = summer(amounts); 

需要注意的是,如果你能保證node.Children永遠不會爲空,夏可簡單了:

summer = node => node.Amount + node.Children.Sum(summer); 

另外,你可以使用空合併運算符:

summer = node => node.Amount + 
       (node.Children ?? Enumerable.Empty<Node>()).Sum(summer); 

當然,你可以把它放在一個單獨的方法改爲:

static decimal SumNodes(Node node) 
{ 
    return node.Amount + 
     (node.Children ?? Enumerable.Empty<Node>()) 
      .Sum((Func<Node, decimal>)SumNodes); 
} 

請注意,這裏的醜是由於方法組轉換中的含糊不清造成的。方法組在類型推斷中沒有太多的愛。

然後致電SumNodes(amount)

using System; 
using System.Collections.Generic; 
using System.Linq; 

class Node 
{ 
    public decimal Amount; 
    public IEnumerable<Node> Children { get; set; } 
} 

public class Test 
{ 
    static void Main() 
    { 
     var amounts = new Node { 
      Amount = 10, Children = new[] { 
       new Node { Amount = 20 }, 
       new Node { Amount = 30 } 
      } 
     }; 

     Func<Node, decimal> summer = null; 
     summer = node => node.Amount + 
      (node.Children == null ? 0m : node.Children.Sum(summer)); 

     decimal total = summer(amounts); 

     Console.WriteLine(total); 
    } 
} 

我不知道我會打電話給任何這些「簡單」的LINQ查詢,請注意...

+0

喬恩,我會再次讚賞這一次,但不會讓我。 – 2009-06-09 10:05:20