带有子项的订购清单 [英] Ordering List with Child Items

查看:66
本文介绍了带有子项的订购清单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉,如果在其他地方询问此问题,但是我一直在寻找合适的答案,但是我发现的大多数信息仅允许单个子项.

Apologies if this is asked elsewhere however I have searched around for a suitable answer, however most of the information I have found allows for single child item only.

我正在尝试编写一个在树形视图风格的界面中显示信息的程序.我面临的问题是我正在从后端数据库中读取以下类:

I'm trying to write a program that displays information in a treeview style interface. The problem I'm facing is that I'm reading the following class from my backend DB:

public class InputClass
{
    public int id { get; set; }
    public string text { get; set; }
    public string icon { get; set; }
    public int? parentId { get; set; }

}

,我正在尝试将其转换为以下类型的列表:

and I'm trying to convert it to a list of the following type:

public class OutputClass
{
    public int id { get; set; }
    public string text { get; set; }
    public string icon { get; set; }
    public List<OutputClass> children { get; set; }
}

如您所见,children属性将在找到其父项时填充.

as you can see, the children property will populate when it finds it's parent item.

作为示例-以下列表:

var inputList = new List<InputClass>();
inputList.Add(new InputClass() { id = 1, text = "Item #1"});
inputList.Add(new InputClass() { id = 2, text = "Item #2" });
inputList.Add(new InputClass() { id = 3, text = "Item #3" });
inputList.Add(new InputClass() { id = 4, text = "SubItem #1", parentId = 1 });
inputList.Add(new InputClass() { id = 5, text = "SubItem #2", parentId = 1 });
inputList.Add(new InputClass() { id = 6, text = "SubItem #3", parentId = 2 });

应输出为:

Item #1
----SubItem #1
----SubItem #2
Item #2
----SubItem #3
Item #3

子级列表中的元素数量不应仅限于一个.关于如何正确排序的任何想法?

the number of elements in the children list should not be limited to just one. Any ideas on how to sort this properly?

推荐答案

var mapping = inputList
    // for each input element, capture the parent id and create the respective output object
    .Select(input => new {
        ParentId = input.parentId,
        Obj = new OutputClass() { id = input.id, text = input.text, icon = input.icon, children = new List<OutputClass>() }
    })
    // create a dictionary so we can look up the elements by id
    .ToDictionary(x => x.Obj.id);

// create target list
List<OutputClass> output = new List<OutputClass>();

// loop through all elements
foreach (var x in mapping.Values)
{
    // if the element has a parent id
    if (x.ParentId.HasValue)
    {
        // find the parent object …
        OutputClass parentObj = mapping[x.ParentId.Value].Obj;
        // … and add this object to the parent’s child list
        parentObj.children.Add(x.Obj);
    }
    else
    {
        // otherwise this is a root element, so add it to the target list
        output.Add(x.Obj);
    }
}

结果将是一个列表,其中包含具有各自层次结构的输入元素.

The result will be a list that contains the input elements with the respective hiearchy.

这是线性时间的解决方案,它只循环两次.此外,它还支持多个级别的层次结构,因此您可以使具有父ID 5的项目生成第三级,等等.

This is a solution in linear time, and it only loops through the items twice. Furthermore, it also supports hierarchies of multiple levels, so you could have items that have a parent id 5 producing a third level, etc.

要产生输出,可以编写一个如下的递归函数:

To produce the output, you could write a recursive function like this:

public static void Print(IEnumerable<OutputClass> elements, string indent="")
{
    foreach (OutputClass element in elements)
    {
        Console.WriteLine("{0}{1} {2}", indent, element.id, element.text);
        Print(element.children, indent + "  ");
    }
}

对于您的输入,这将产生以下结果:

For your input, this produces the following result:

1 Item #1
  4 SubItem #1
  5 SubItem #2
2 Item #2
  6 SubItem #3
3 Item #3


作为示例,以下输入列表使用与上面相同的转换代码生成下面的输出:


And just as an example, the following input list produces the output below, using the same conversion code as above:

var inputList = new List<InputClass>()
{
    new InputClass() { id = 1, text = "Item 1" },
    new InputClass() { id = 2, text = "Item 2" },
    new InputClass() { id = 3, text = "Item 3" },
    new InputClass() { id = 4, text = "SubItem 1.1", parentId = 1 },
    new InputClass() { id = 5, text = "SubItem 1.2", parentId = 1 },
    new InputClass() { id = 6, text = "SubItem 2.1", parentId = 2 },
    new InputClass() { id = 7, text = "SubItem 2.2", parentId = 2 },
    new InputClass() { id = 8, text = "SubItem 1.2.1", parentId = 5 },
    new InputClass() { id = 9, text = "SubItem 1.2.2", parentId = 5 },
    new InputClass() { id = 10, text = "SubItem 1.2.1.1", parentId = 8 },
    new InputClass() { id = 11, text = "SubItem 2.1.1", parentId = 6 },
    new InputClass() { id = 12, text = "SubItem 2.1.1.1", parentId = 11 },
    new InputClass() { id = 13, text = "SubItem 2.1.1.1.1", parentId = 12 },
    new InputClass() { id = 14, text = "SubItem 2.1.1.1.2", parentId = 12 }
};

输出:

1 Item 1
  4 SubItem 1.1
  5 SubItem 1.2
    8 SubItem 1.2.1
      10 SubItem 1.2.1.1
    9 SubItem 1.2.2
2 Item 2
  6 SubItem 2.1
    11 SubItem 2.1.1
      12 SubItem 2.1.1.1
        13 SubItem 2.1.1.1.1
        14 SubItem 2.1.1.1.2
  7 SubItem 2.2
3 Item 3

这篇关于带有子项的订购清单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆