c# - 订购父/子列表
问题描述
我在根据父子对列表进行排序时遇到问题。
这是截面对象的模型:
public class Section
{
public int Id { get; set; } //dont care
public int SectionID { get; set; } //the actual ID I use
public int SectionRowId { get; set; } //something else
public string Name { get; set; } //just display
public int ParentID { get; set; } //parent id connection
}
有一个可以按任何混合顺序排列的部分列表。
Random R = new Random().Next(1000);
new Section() { Id = 9, Name = R.Next(1000).ToString(), SectionID = 900, SectionRowId = 1, ParentID = 3 }
,new Section() { Id = 5, Name = R.Next(1000).ToString(), SectionID = 137, SectionRowId = 4, ParentID = 0 }
,new Section() { Id = 8, Name = R.Next(1000).ToString(), SectionID = 3, SectionRowId = 3, ParentID = 137 }
,new Section() { Id = 1, Name = R.Next(1000).ToString(), SectionID = 888, SectionRowId = 1, ParentID = 0 }
,new Section() { Id = 3, Name = R.Next(1000).ToString(), SectionID = 137, SectionRowId = 2, ParentID = 0 }
,new Section() { Id = 4, Name = R.Next(1000).ToString(), SectionID = 137, SectionRowId = 3, ParentID = 888 }
,new Section() { Id = 6, Name = R.Next(1000).ToString(), SectionID = 3, SectionRowId = 1, ParentID = 0 }
,new Section() { Id = 7, Name = R.Next(1000).ToString(), SectionID = 3, SectionRowId = 2, ParentID = 0 }
,new Section() { Id = 2, Name = R.Next(1000).ToString(), SectionID = 137, SectionRowId = 1, ParentID = 0 }
,new Section() { Id = 10, Name = R.Next(1000).ToString(), SectionID = 11, SectionRowId = 1, ParentID = 900 }
,new Section() { Id = 11, Name = R.Next(1000).ToString(), SectionID = 8, SectionRowId = 1, ParentID = 137 }
,new Section() { Id = 12, Name = R.Next(1000).ToString(), SectionID = 8, SectionRowId = 2, ParentID = 0 }
预期结果:
Id SectionId / SectionRowId (Parent SectionID)
01) - [ 888 / 001 ]
02) - [ 137 / 001 ]
03) - [ 137 / 002 ]
04) - [ 137 / 003 ] <- 888 // is available before ^^
05) - [ 137 / 004 ]
06) - [ 003 / 001 ]
07) - [ 003 / 002 ]
08) - [ 003 / 003 ] <- 137 // is available before ^^
09) - [ 900 / 001 ] <- 003 // is available before ^^
10) - [ 011 / 001 ] <- 900 // is available before ^^
11) - [ 008 / 001 ] <- 137 // is available before ^^
12) - [ 008 / 002 ]
上述预期结果的图例:
Example 04) - [ 137 / 003 ] <- 888 // is available before ^^
888 是 137 的父代,它在此之前可用。
01) - [ 888 / 001 ]
如果低于这个,那就不好了。
编辑:
请查看:https ://dotnetfiddle.net/FCZF5X#&togetherjs=aIbJ64NwJv 我已将其添加为完全随机的并对其进行检查。所以可能更容易理解。
从新的随机代码来看,它应该是这样的:
Items count: 12
Final result is: True
[ ORIGINAL LIST ] | [ SORTED LIST ]
-----------------------------------------------------------------------------------------------
ID | Section / Row | Parent | ID | Section / Row | Parent
025116) - [ 004337 / 084754 ] <-- 011973 | 008134) - [ 011973 / 018572 ]
028628) - [ 006663 / 045806 ] <-- 011973 | 083009) - [ 011973 / 013626 ]
099494) - [ 004337 / 075769 ] <-- 006663 | 080161) - [ 011973 / 023149 ]
051824) - [ 004337 / 086590 ] | 059540) - [ 011973 / 045751 ]
008134) - [ 011973 / 045751 ] | 078203) - [ 011973 / 061979 ]
002017) - [ 005938 / 073913 ] <-- 011973 | 025800) - [ 006663 / 045806 ]
083009) - [ 011973 / 023149 ] | 028628) - [ 006663 / 082944 ] <-- 011973
037537) - [ 005938 / 038984 ] <-- 004337 | 051824) - [ 004337 / 075769 ]
025800) - [ 006663 / 082944 ] | 099494) - [ 004337 / 084754 ] <-- 006663
080161) - [ 011973 / 018572 ] | 025116) - [ 004337 / 086590 ] <-- 011973
059540) - [ 011973 / 061979 ] | 037537) - [ 005938 / 038984 ] <-- 004337
078203) - [ 011973 / 013626 ] | 002017) - [ 005938 / 073913 ] <-- 011973
上面的排序列表摘要^^:
- ID = 不重要
- Section = 必须组合在一起
- 行 = 必须按升序排列
- Parent =如果有,则父节组必须在该组之上。
解决方案
这就是我现在解决它的方法......如果其他人将来需要的话。
private static List<Section> SortTheList(List<Section> messyList)
{
List<Section> newList = new List<Section>();
List<Section> outList = new List<Section>();
newList.AddRange(messyList);
int[] sectionIDs = newList.Select(x => x.SectionID).Distinct().ToArray();
int[] no = GetOrder(newList).ToArray();
foreach (int sectionID in no)
{
IEnumerable<Section> thisSectionGroup = newList.Where(x => x.SectionID == sectionID);
thisSectionGroup = thisSectionGroup.OrderBy(x => x.SectionRowId).ThenBy(x => x.ParentID);
outList.AddRange(thisSectionGroup);
}
return outList;
}
private static List<int> GetOrder(List<Section> allSections)
{
Dictionary<int, int> orderList = new Dictionary<int, int>();
int[] sectionIDs = allSections.Select(x => x.SectionID).Distinct().ToArray();
foreach (int sectionID in sectionIDs) { orderList.Add(sectionID, 0); }
foreach (int sectionID in sectionIDs)
{
int[] parentIDs = allSections.Where(x => x.SectionID == sectionID && x.ParentID > 0).Select(x => x.ParentID).ToArray();
foreach (int parentID in parentIDs)
{
IncParents(allSections, parentID, ref orderList);
}
}
return orderList.OrderByDescending(x => x.Value).Select(x => x.Key).ToList();
}
private static void IncParents(List<Section> allSections, int parentID, ref Dictionary<int, int> orderList, int incLevel = 1)
{
orderList[parentID] = orderList[parentID] + incLevel;
int[] parentIDs = allSections.Where(x => x.SectionID == parentID && x.ParentID > 0).Select(x => x.ParentID).ToArray();
foreach (int subParentID in parentIDs)
{
IncParents(allSections, subParentID, ref orderList, (incLevel + 1));
}
}
https://dotnetfiddle.net/1VNqSB
随意改进它或使它更优雅:)
推荐阅读
- flutter - Generate Flutter Local Notification when background FCM Triggers
- python - 通过python连接MySQL并为变量分配值时,数据类型从'int'更改为'tuple'
- ios - URLSessionDataTask 没有成员“地图”Swift 5
- c# - SQL Server 插入问题。数据插入操作成功,但关闭应用程序重新打开后找不到数据
- mqtt - 如何在 eclipse-mosquitto 中使用 QoS MQTT 接收离线客户端的消息?
- go - 尝试下载 git 存储库时 pkg-config 出错
- python - python覆盖一个不同名称的api类方法
- javascript - 为什么我在 v-for 的插槽中只有一个元素?
- laravel - Route:list 在本地机器上工作,但在 laravel 的服务器上出错
- java - 为什么文件没有写入内部存储?