2013-04-05 59 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