获取层次结构中实体的父级

发布于 2024-10-02 23:23:19 字数 1359 浏览 5 评论 0原文

几天来一直试图解决这个问题但没有任何进展,我的问题是:

给定层次结构中的实体,返回 直系后代列表(或 实体的父s)。

当我想知道“Entity 1.2.2.2”的层次结构时,它将返回一个仅包含粗体项目的列表:

Entity 1
- Entity 1.1
- Entity 1.2
  - Entity 1.2.1
  - Entity 1.2.2
    - Entity 1.2.2.1
    - Entity 1.2.2.2
  - Entity 1.2.3
  - Entity 1.2.4
    - Entity 1.2.4.1
- Entity 1.3
- Entity 1.4
Entity 2
...

因此,预期结果:

Entity 1
- Entity 1.2
  - Entity 1.2.2
    - Entity 1.2.2.2

实现代码:

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

    public bool AbsoluteParent 
    { 
        get
        { 
            return Parent == null;
        } 
    }

    public IEnumerable<Entity> Hierarchy //problem
    { 
        get
        {
            return AbsoluteParent 
                ? new [] { this }
                : new [] { this }.Concat( Parent.Hierarchy );
        }
    }

}

上面的数组尝试只是我一直在尝试的选项之一,该代码实际上返回类似的内容:

Entity 1
Entity 1
- Entity 1.2
Entity 1
- Entity 1.2
  - Entity 1.2.2
Entity 1
- Entity 1.2
  - Entity 1.2.2
    - Entity 1.2.2.2

我能够使用 jQuery 的 parents() 函数实现预期结果,我一直在阅读 yield return 关键字,但仍然停留在它的 more (我猜)功能性风格,我还在初级阶段。

Been trying to solve this without progress for a couple days, my question:

Given an entity in a hierarchy, return
a list of the immediate-ascendants (or
parents) of the entity.

When I want to know the hierarchy of "Entity 1.2.2.2" it would return a list containing only the bold items:

Entity 1
- Entity 1.1
- Entity 1.2
  - Entity 1.2.1
  - Entity 1.2.2
    - Entity 1.2.2.1
    - Entity 1.2.2.2
  - Entity 1.2.3
  - Entity 1.2.4
    - Entity 1.2.4.1
- Entity 1.3
- Entity 1.4
Entity 2
...

Hence, expected result:

Entity 1
- Entity 1.2
  - Entity 1.2.2
    - Entity 1.2.2.2

Implementation code:

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

    public bool AbsoluteParent 
    { 
        get
        { 
            return Parent == null;
        } 
    }

    public IEnumerable<Entity> Hierarchy //problem
    { 
        get
        {
            return AbsoluteParent 
                ? new [] { this }
                : new [] { this }.Concat( Parent.Hierarchy );
        }
    }

}

The array attempt above is just one of the options I have been trying, that code actually returns something like:

Entity 1
Entity 1
- Entity 1.2
Entity 1
- Entity 1.2
  - Entity 1.2.2
Entity 1
- Entity 1.2
  - Entity 1.2.2
    - Entity 1.2.2.2

I am able to achieve the expected results using jQuery's parents() function, I've been reading the yield return keywords but still stuck in its more (I guess) functional style which I'm still baby-stepping into.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

迭代器块可以接受吗?

public IEnumerable<Entity> Hierarchy
{
    // note: buffers results
    get { return UpwardHierarchy.Reverse(); }    
}

public IEnumerable<Entity> UpwardHierarchy
{
    get
    {
        // genuine lazy streaming
        for (var entity = this; entity != null; entity = entity.Parent)
            yield return entity;
    }
}

另一种选择:使用 MoreLinq 的 生成

return MoreEnumerable.Generate(this, entity => entity.Parent)
                     .TakeWhile(entity => entity != null)
                     .Reverse();

Is an iterator block acceptable?

public IEnumerable<Entity> Hierarchy
{
    // note: buffers results
    get { return UpwardHierarchy.Reverse(); }    
}

public IEnumerable<Entity> UpwardHierarchy
{
    get
    {
        // genuine lazy streaming
        for (var entity = this; entity != null; entity = entity.Parent)
            yield return entity;
    }
}

Another option: Using MoreLinq's Generate:

return MoreEnumerable.Generate(this, entity => entity.Parent)
                     .TakeWhile(entity => entity != null)
                     .Reverse();
林空鹿饮溪 2024-10-09 23:23:19

正如 @Ani 对他的答案的评论,没有办法从根获得惰性层次结构。

有一个有趣的执行方式表,显示了“Reverse() ”方法作为“延迟非流执行”。因此,它仅在您访问其第一项(根)时进行评估,但它需要读取整个 UpwardHierarchy 才能生成第一项。

如果您想要性能,您应该注意 linq(以及任何“yield return”方法)生成 IEnumerable<> 的方式。如果您只想在 Hierarchy 枚举上迭代一次,则可以忽略此警报,但如果您打算多次搜索 Hierarchy 项,则最好调用 ToList() 以避免重新处理 UpwardHierarchy 和“Reverse()” ”。

一些代码:

[TestClass]
public class HierarchyTest
{
    #region Ani's code
    class Entity
    {
        public Entity Parent { get; set; }

        public IEnumerable<Entity> Hierarchy
        {
            // note: buffers results
            get { return UpwardHierarchy.Reverse(); }
        }

        public int YieldCount = 0;//modified
        public IEnumerable<Entity> UpwardHierarchy
        {
            get
            {
                // genuine lazy streaming
                for (var entity = this; entity != null; entity = entity.Parent)
                {
                    YieldCount++;//modified
                    yield return entity;
                }
            }
        }
    }
    #endregion


    [TestMethod]
    public void TestMethod1()
    {
        /*
        Entity 1
        - Entity 1.2
          - Entity 1.2.2
            - Entity 1.2.2.2
         */
        var e1 = new Entity();
        var e12 = new Entity() { Parent = e1 };
        var e122 = new Entity() { Parent = e12 };
        var e1222 = new Entity() { Parent = e122 };

        var hierarchy = e1222.Hierarchy;
        Assert.AreEqual(0, e1222.YieldCount);//nothing was evaluated until now
        hierarchy.First();
        Assert.AreEqual(4, e1222.YieldCount);//the entire UpwardHierarchy has been yielded to get the first Hierarchy item
        hierarchy.First();
        Assert.AreEqual(8, e1222.YieldCount);//yielded all UpwardHierarchy  itens again to get the first Hierarchy item

        List<Entity> evaluatedHierarchy = e1222.Hierarchy.ToList();//calling ToList() produces a List<Entity> instance so UpwardHierarchy and Reverse() are evaluated only once
        Assert.AreEqual(12, e1222.YieldCount);//Yieldcount+=4 because of ToList()
        evaluatedHierarchy.First();
        Assert.AreEqual(12, e1222.YieldCount);//and now you can use evaluatedHierarchy as you wish without causing another UpwardHierarchy and Reverse() call.
        evaluatedHierarchy.First();
        Assert.AreEqual(12, e1222.YieldCount);
    }
}

As @Ani comments on his answer, there is no way to get a lazy hierarchy from the root.

There is an interesting manner of execution table that shows the "Reverse()" method as "Deferred Non-Streaming Execution". So its only evaluated when you access its first item (root) but it needs to read the entire UpwardHierarchy to yield this first item.

If you want performance, something you should pay atention is the way linq (and any "yield return" method) produces the IEnumerable<>. If you are going to iterate only once on Hierarchy enumerable its ok to ignore this alert, but if you are going to search Hierarchy items several times its a good idea to call ToList() to avoid re-processing both UpwardHierarchy and "Reverse()".

Some code:

[TestClass]
public class HierarchyTest
{
    #region Ani's code
    class Entity
    {
        public Entity Parent { get; set; }

        public IEnumerable<Entity> Hierarchy
        {
            // note: buffers results
            get { return UpwardHierarchy.Reverse(); }
        }

        public int YieldCount = 0;//modified
        public IEnumerable<Entity> UpwardHierarchy
        {
            get
            {
                // genuine lazy streaming
                for (var entity = this; entity != null; entity = entity.Parent)
                {
                    YieldCount++;//modified
                    yield return entity;
                }
            }
        }
    }
    #endregion


    [TestMethod]
    public void TestMethod1()
    {
        /*
        Entity 1
        - Entity 1.2
          - Entity 1.2.2
            - Entity 1.2.2.2
         */
        var e1 = new Entity();
        var e12 = new Entity() { Parent = e1 };
        var e122 = new Entity() { Parent = e12 };
        var e1222 = new Entity() { Parent = e122 };

        var hierarchy = e1222.Hierarchy;
        Assert.AreEqual(0, e1222.YieldCount);//nothing was evaluated until now
        hierarchy.First();
        Assert.AreEqual(4, e1222.YieldCount);//the entire UpwardHierarchy has been yielded to get the first Hierarchy item
        hierarchy.First();
        Assert.AreEqual(8, e1222.YieldCount);//yielded all UpwardHierarchy  itens again to get the first Hierarchy item

        List<Entity> evaluatedHierarchy = e1222.Hierarchy.ToList();//calling ToList() produces a List<Entity> instance so UpwardHierarchy and Reverse() are evaluated only once
        Assert.AreEqual(12, e1222.YieldCount);//Yieldcount+=4 because of ToList()
        evaluatedHierarchy.First();
        Assert.AreEqual(12, e1222.YieldCount);//and now you can use evaluatedHierarchy as you wish without causing another UpwardHierarchy and Reverse() call.
        evaluatedHierarchy.First();
        Assert.AreEqual(12, e1222.YieldCount);
    }
}
萌化 2024-10-09 23:23:19

这不是一种非常 LINQ 的方式(我的 LINQ 仍然很新):

List<Entity> graph = new List<Entity>()
Entity current = this;

while (current != null) {
   graph.Add(current);
   current = current.Parent;
}

graph.Reverse();

return graph;

Not a very LINQ way of doing it (my LINQ is still pretty new):

List<Entity> graph = new List<Entity>()
Entity current = this;

while (current != null) {
   graph.Add(current);
   current = current.Parent;
}

graph.Reverse();

return graph;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文