【问题标题】:Get the Depth of an object tree of objects with the same type using LAMBDA expression使用 LAMBDA 表达式获取具有相同类型的对象的对象树的深度
【发布时间】:2014-01-23 12:41:18
【问题描述】:

我有这个对象:

public class dtHeader
{
    public dtHeader ParentHeader { get; set; }
    public string HeaderText { get; set; }
    public string DataField { get; set; }
    public bool Visible { get; set; }
    public int DisplayOrder { get; set; }
}

我想用lambda表达式计算,物体的深度,物体本身存在多少层?

我看到了this JavaScript post,但我正在努力将其转换为单行 lambda 语句。

假设对象是这样的new dtHeader(){ ParentHeader = null, HeaderText = "col1" }; 结果将是 1

对于new dtHeader(){ ParentHeader = new dtHeader(){ ParentHeader = null, HeaderText = "col1" }, HeaderText = "col1" };,结果为 2

我想通过list<dtHeader> 来实现这一点,因此其中一些的深度为 1,而另一些的深度更深,并且想要最深的深度。

    _______ITEM_IN_LIST_OBJECT__
    ______1___2___3___4___5___6_
 D  1.  |_o_|_o_|_o_|_o_|_o_|_o_|
 E  2.  |_o_|___|_o_|___|_o_|_o_|
 P  3.  |___|___|_o_|___|_o_|___|
 T  4.  |___|___|___|___|_o_|___|
 H  5.  |___|___|___|___|_o_|___|

它必须无限地深入(直到它允许对象在彼此内部堆积)深。

var HeaderLayerCount = lDtCol.Where(n => n.ParentHeader != null)
                             .Where(n => n.ParentHeader.ParentHeader != null)
                             .Where(n => n.ParentHeader.ParentHeader.ParentHeader != null);

编辑: 我只想补充一点,如果你想在特定的深度级别上工作,例如深度为 3 的所有对象,你可以在类中使用这个额外的递归函数

public class dtCol
{
    public dtCol ParentHeader { get; set; }
    public string HeaderText { get; set; }
    public string DataField { get; set; }
    public bool Visible { get; set; }
    public int DisplayOrder { get; set; }
    public int Depth { get { return ParentHeader != null ? ParentHeader.Depth + 1 : 1; } }
    public int CurrentDepth { get; set; } //Set on initialisation
    public dtCol getParent(dtCol col, int getDepth) //Gets the parent on a specific level after the first base level (1) else returns the previous not null child
    {
        return (col.ParentHeader != null && col.ParentHeader.CurrentDepth == getDepth) ? col.ParentHeader : this.getParent(col.ParentHeader, getDepth);
    }
}

你可以这样使用它:

var HeaderLayerCount = lDtCol.OrderByDescending(n => n.Depth).First().Depth;
for (int hlc = 1; hlc <= HeaderLayerCount; hlc++)
{
    var headerrow = new List<dtCol>();
    //This foreach adds the parent header if not null else adds the not null child
    lDtCol.ForEach(n =>
    {
        var h = n.getParent(n, hlc); //Get Parent, null is returned if parent does not exists
        headerrow.Add((h != null) ? h : n); //If parent is null, add base dtCol so that the headers can be merged upwards.
    });

    //Do what you need with your new single dimensional list of objects
}

【问题讨论】:

    标签: c# algorithm object lambda generic-list


    【解决方案1】:

    为什么不在你的类上实现一个 int GetDepth() 方法,它会到达最顶层的祖先,计算每个级别?

    您的查询会简单得多。

    我被弗罗德打败了,向他致敬

    我有相同的实现:

     public int GetDepth()
            {
                if (ParentHeader == null)
                {
                    return 1;
                }
                else return 1 + ParentHeader.GetDepth();
            }
    

    【讨论】:

    • 这听起来是一个非常好的主意,您能否发布一个示例,说明您将如何做到这一点?
    【解决方案2】:
    using System;
    using System.Linq;
    
    namespace ConsoleApplication3
    {
        public class dtHeader
        {
            public dtHeader ParentHeader { get; set; }
            public string HeaderText { get; set; }
            public string DataField { get; set; }
            public bool Visible { get; set; }
            public int DisplayOrder { get; set; }
            public int Depth
            {
                get
                {
                    // If header has parent, then this depth is parent.depth + 1
                    if (ParentHeader != null)
                        return ParentHeader.Depth+1;
                    else
                        return 1; // No parent, root is depth 1
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                dtHeader[] headers = { 
                                         new dtHeader { HeaderText = "dt1" },
                                         new dtHeader { HeaderText = "dt2" },
                                         new dtHeader { HeaderText = "dt3" },
                                         new dtHeader { HeaderText = "dt4" },
                                         new dtHeader { HeaderText = "dt5" }
                                     };
    
                headers[1].ParentHeader = headers[0];
                headers[2].ParentHeader = headers[1];
                headers[3].ParentHeader = headers[2];
                headers[4].ParentHeader = headers[3];
    
                var deepest = headers.OrderByDescending(item=>item.Depth).First();
                Console.WriteLine(deepest.Depth+ ", " + deepest.HeaderText);
    
                var runner = deepest;
                while (runner.ParentHeader != null)
                    runner = runner.ParentHeader;
    
                Console.WriteLine("The deepest root header is:" + runner.HeaderText);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      这里有一个 lambda 表达式来得到你想要的:

      Func<dtHeader, int> getDepth = null;
      getDepth = dth =>
      {
          var depth = 1;
          if (dth.ParentHeader != null)
          {
              depth += getDepth(dth.ParentHeader);
          }
          return depth;
      };
      

      您必须将其定义为两部分(分配 null 和分配主体)才能让递归工作。

      【讨论】:

      • 这将始终返回 1。您也需要将深度传递给 getDepth Func
      • @jabko87 - 不,这个功能工作得很好。这个想法是它返回深度 - 它不需要传递它来做到这一点。
      【解决方案4】:

      我修改了 Enigmativity 的答案以使其正常工作:

      Func<dtHeader, int, int> getDepth = null;
      getDepth = (dth, depth) =>
      {
          if (dth.ParentHeader != null)
          {
              depth = getDepth(dth.ParentHeader, ++depth);
          }
      
          return depth;
      };
      

      这样称呼它:

      int depth = getDepth(header, 0)
      

      【讨论】:

      • 这完全没有必要。我的功能运行良好。
      • 您的代码实际上是错误的。您正在调用getDepth(header, 0),它将返回比所需值少1。您的代码要求调用者知道初始深度。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 1970-01-01
      • 2018-03-11
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多