【问题标题】:Creating a hierarchical list from flat LINQ results从平面 LINQ 结果创建分层列表
【发布时间】:2016-05-05 00:04:30
【问题描述】:

希望有人可以评论一种更有效的方法:我有一个代表用户待办事项列表的通用工作项列表。目前,这仅按截止日期排序并显示在 Obout Treeview 中,并且工作正常。

现在我们希望通过允许用户对他们的待办事项列表进行排序来更新这一点树视图将主要排序显示为父级,将次要排序显示为子级。实际项目将显示为孙子项目,如下所示:

Due Date
- Received Date
-- Work Item
-- Work Item
- Received Date
-- Work Item 
Due Date

...等

据我所知,关于 Treeview 有一些关键的限制:

  1. 父节点必须在子节点之前创建
  2. 节点一旦创建就不能删除
  3. 没有方法可以查看是否存在其他节点(父节点、兄弟节点、子节点),因此您无法以编程方式判断节点是否会在服务器端重复。

我正在修改一些旧代码,因此请对我的示例保持温和。我不得不拿出很多东西来澄清它在做什么。

public void generateOboutTreeContent()
{
    // Add unique root nodes.
    switch (primarySort)
    {
        [...]
        case SortOption.ByDueDate:
            addNodesForDueDates(true);
            break;
        [...]
    }

    // Then add child nodes for each root node.
    switch (secondarySort)
    {
        [...]
        case SortOption.ByReceivedDate:
            addNodesForReceivedDates();
            break;
        [...]
    }

    // Finally, add all the actual items as grandchildren.
    foreach (WorkItem item in WorkQueue)
    {
        tree.Add(parentID, item.ID, item.url, false);
    }
}

private void addNodesForDueDates(bool isRootNode = false)
{
    var uniqueNodes = workQueue.GroupBy(i => i.DueDate).Select(group => group.First()).ToList();
    foreach (classWorkItem node in uniqueNodes)
    {
        var dueDate = node.DueDate;
        if (isRootNode)
        {
            tree.Add("root", dueDate, dueDate , false);
        }
        else
        {
            tree.Add(parentID, dueDate, dueDate, false);
        }
    }
}

我怎样才能更有效地从通用列表中为 Obout 树创建根优先层次结构,并且一次又一次地遍历数据集以获取唯一值?

使用硬编码排序创建结构已经够麻烦了,但是尝试以一种干净利落地允许用户定义排序(没有子类或方法的爆炸式增长)的方式对此进行编码真的让我很难过。我很想听听任何建议!

谢谢。

【问题讨论】:

  • 参见维基文章:en.wikipedia.org/wiki/Tree_sort
  • @jdweng 尽管这个问题与树和排序有关,但这并不能真正解决问题。
  • 是的。问题是:1)“希望有人可以评论一种更有效的方法来做到这一点”。2)“我怎样才能更有效地为 Obout 创建根优先层次结构通用列表中的树,一次又一次地遍历数据集以获得唯一值”?文章(和链接)完全解释了进行树排序的方法。问题没有要求对解决方案进行编码。我的问题是 Linq 是否真的会更有效率。 “通常”Linq 比非 Linq 解决方案使用更多的内存和更多的处理时间。除非进行时间测试,否则我们不会知道。

标签: c# linq treeview obout


【解决方案1】:

您不是按这些日期排序数据,而是按这些数据分组数据(然后对这些组进行排序)。

要根据字段对项目进行分组,只需使用GroupBy

您只需按第一个字段对您的项目进行分组,在第二个字段上对每个组进行分组,并根据需要添加排序子句以对组本身进行排序。

var query = from item in data
            group item by item.DueDate into dueDateGroup
            orderby dueDateGroup.Key
            select from item in dueDateGroup
                    group item by item.RecievedDate into recievedDateGroup
                    orderby recievedDateGroup.Key
                    select recievedDateGroup;

或者,如果您更喜欢使用方法语法:

var query2 = data.GroupBy(item => item.DueDate)
    .OrderBy(group => group.Key)
    .Select(dueDateGroup =>
        dueDateGroup.GroupBy(item => item.RecievedDate)
            .OrderBy(group => group.Key));

将数据转换为适当的模型后,将该模型转换为 TreeView 应该很简单,您只需迭代每个组并为该组创建一个项目,然后迭代该组中的项目添加子节点为每个项目,并为那些孩子(他们自己是组)做同样的事情来添加孙子。

【讨论】:

  • 谢谢,我试试这个。我希望这应该清理现有代码相当多。
猜你喜欢
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2012-12-20
相关资源
最近更新 更多