2013-04-05 16 views
4

我對使用linq表達式並試圖重構一些舊代碼相當陌生。有沒有辦法將下面的方法變成簡潔而乾淨的Linq表達式?使用Linq計數父對象

public int GetParentCount(object o) 
{ 
    int count = 0; 
    object parent = GetParentObject(o); 
    while (parent != null) 
    { 
     count++; 
     parent = GetParentObject(parent); 
    } 
    return count; 
} 

我試圖尋找,但沒有得到滿意的結果

+4

你爲什麼要用LINQ來做這件事? – MoonKnight 2013-04-05 14:58:33

+1

你可以發佈相關對象的結構嗎?此外,GetParentObject實際上做了什麼 - 它如何獲得父級? – Floremin 2013-04-05 14:58:42

+4

我看到沒有遞歸... – 2013-04-05 15:01:37

回答

2

您可以枚舉祖先像這樣:

public IEnumerable<MyClass> AncestorsOf(MyClass obj) 
{ 
    var parent = GetParentObject(obj); 
    if (parent != null) 
    { 
     yield return parent; 
     foreach(var grandparent in AncestorsOf(parent)) 
      yield return grandparent; 
    } 
} 

獲得總計數則是一個簡單AncestorsOf(obj).Count()

+0

+1我剛剛提出此建議 – 2013-04-05 15:02:56

+3

僅供參考這在技術上不是LINQ,它只是一個迭代器塊。這是一種和LINQ很好的方法,但它本身不是LINQ。重構使其遞歸也沒有幫助。這使得它效率很低。如果你保持相同的迭代方法,OP使用它可以更有效地做同樣的事情。 – Servy 2013-04-05 15:05:38

+0

正確,「Linq」的唯一位是Count()。 Linq基本上只對集合進行操作,所以你需要創建一些IEnumerable/IQueryable。我不認爲你可以將遞歸轉換爲可實現的用於祖先的IEnumerable,或遞歸地生成父類的可枚舉的短小。我可能是錯的。 – 2013-04-05 15:23:26

1

作爲Ander解決方案的替代方案,非遞歸方法:

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

namespace Demo 
{ 
    static class Program 
    { 
     static void Main() 
     { 
      var obj = new object(); 
      int count = AllParents(obj).Count(); // Using Linq only here. 
      Console.WriteLine(count); 
     } 

     public static IEnumerable<object> AllParents(object obj) 
     { 
      while (true) 
      { 
       obj = GetParentObject(obj); 

       if (obj == null) 
        yield break; 

       yield return obj; 
      } 
     } 

     // This is merely a hacky test implementation. 
     public static object GetParentObject(object obj) 
     { 
      if (--count == 0) 
       return null; 

      return obj; 
     } 

     private static int count = 10; 
    } 
} 
0

這裏的一個通用的功能,可以在任何類型的對象進行操作,用含有親任何對象名稱(使用Func<T,T>):

public static class MyExtensions { 

    /// <summary>Gets an enumerable of all ancestors.</summary> 
    public static IEnumerable<T> Ancestors<T>(this T obj, Func<T, T> expr) where T : class { 
    obj = expr.Invoke(obj); 
    while(obj != null) { 
     yield return obj; 
     obj = expr.Invoke(obj); 
    } 
} 

下面是一個使用該函數的示例性應用:

class MyClass { 
    public MyClass Parent { get; set; } 
} 

void Main() 
{ 
    MyClass a = new MyClass(); 
    a.Parent = new MyClass(); 
    a.Parent.Parent = new MyClass(); 

    a.Ancestors(myObj => myObj.Parent).Count(); // Result: 2 
} 
+0

如果您還想要計算序列的方法,因爲您始終可以對其調用「計數」,所以創建一個方法*只是執行計數沒有實際意義。我只是沒有增加價值。當然,這個答案也有與被接受的答案一樣的問題。它實際上並沒有使用LINQ來解決這個問題,它只是創建一個迭代器塊。 LINQ和迭代器塊是兩個完全不同的東西,即使一個使用另一個。 – Servy 2015-03-31 20:20:41

+0

@Servy我原本只有'AncestorCount',但贊成'祖先().Count()',我已經刪除它。 LINQ不僅僅是查詢數據集的一種方式嗎?這不是一個可枚舉的,而是一個對象,所以也許這就是區別。我主要是把這裏作爲以前的答案的改進版本,所以希望它會提供一些價值。 – bradlis7 2015-03-31 21:12:46

+0

是的,LINQ是用於查詢數據集的功能集合,但問題在於它的要求非常具體,沒有答案能夠回答它。 – Servy 2015-04-01 13:57:43