我目前正在尝试使用LINQ和C#找到一种好的方式来对我的元素进行排序,但我似乎做不到。
现在假设你有以下表格:
---TempTable
ID (int)
ParentID (int)
Name (varchar)
SortOrder (int)
ID和ParentID彼此相关,并为我提供了自我分层数据结构。根元素在ID字段中有一个null。 SortOrder仅是整个表的一部分,并基于ParentID,因此共享相同ParentID的元素确实具有其中的1、2、3。
让我们进一步假设以下数据:
ID = 1
ParentID = null
Name = Test 1
SortOrder = 1
ID = 2
ParentID = 1
Name = Test 2
SortOrder = 1
ID = 3
ParentID = 1
Name = Test 3
SortOrder = 2
ID = 4
ParentID = 2
Name = Test 4
SortOrder = 1
我期望的平面列表应按以下顺序排列:
Test 1 //root element with sort order 1 = very top
Test 2 //child element of root with sort order 1
Test 4 //child element of test 2 with sort order 1
Test 3 //child element of root with sort order 2
另外,我希望能够获得对象本身,而不仅仅是通过使用select new ...获取部分信息。
这是我失败尝试之一:
from x in EntityModel.TempTables //DbSet<TempTable> by EntityFramework - which already holds all elements
orderby x.SortOrder
from y in x.TempTableChildren //Navigation Property by EntityFramework
orderby y.SortOrder
select y
感谢您提前的帮助。
编辑:
根据给定的TestData,使用ParentID排序可能会有所帮助,因为ID和ParentIDs是完美排序的。但在实际应用中,情况并非如此,因为它是数据驱动的。某些人可能会删除一个条目,创建一个新的条目,并将其按照某个父项的顺序放置,这样就会出现以下情况:
ID = 193475037
ParentID = 2
Name = Test 192375937
SortOrder = 25
现在,在应用程序中,可以移动这个项目,ParentID和SortOrder会随机更改为类似以下内容:
ID = 193475037
ParentID = 456798424
Name = Test 192375937
SortOrder = 4
为了进一步解释这个问题,这里有一些代码 - 在没有一个漂亮的Linq查询的情况下,我将如何使用两个yield return进行操作:
public class LinqTestDemo
{
Random rand = new Random();
List<TempTable> list = new List<TempTable>();
public List<TempTable> GetFlatData()
{
list = GetTestData();
var rootElement = (from x in list
where x.ParentID == null
orderby x.SortOrder
select x).ToList();
var flatList = OrderChilds(rootElement).ToList();
foreach (var tempTable in flatList)
{
Console.WriteLine(string.Format("ID = {0} - ParentID = {1} - Name = {2} - SortOrder = {3}", tempTable.ID, tempTable.ParentID, tempTable.Name, tempTable.SortOrder));
}
return flatList;
}
private IEnumerable<TempTable> OrderChilds(List<TempTable> enumerable)
{
foreach (var tempTable in enumerable)
{
yield return tempTable;
TempTable table = tempTable;
var childs = OrderChilds((from x in list
where x.ParentID == table.ID
orderby x.SortOrder
select x).ToList());
foreach (var child in childs)
{
yield return child;
}
}
}
public List<TempTable> GetTestData()
{
var returnValue = new List<TempTable>();
for (int i = 0; i < 50; i++)
{
var tempTable = new TempTable();
tempTable.ID = i;
if (i == 0)
tempTable.ParentID = null;
else
tempTable.ParentID = rand.Next(0, i);
var maxSortOrder = (from x in returnValue
where x.ParentID == tempTable.ParentID
select (int?)x.SortOrder).Max();
if (maxSortOrder.HasValue)
tempTable.SortOrder = maxSortOrder.Value + 1;
else
tempTable.SortOrder = 1;
tempTable.Name = string.Format("Test {0:00}", i);
returnValue.Add(tempTable);
}
return returnValue;
}
public class TempTable
{
public int ID { get; set; }
public int? ParentID { get; set; }
public string Name { get; set; }
public int SortOrder { get; set; }
}
}
@ 广度优先遍历 vs 深度优先遍历: 经过阅读后,我想选择深度优先遍历,其中在同一深度级别的元素应按SortOrder属性排序。