【问题标题】:Order a parent/child list订购父/子列表
【发布时间】:2019-05-10 12:31:38
【问题描述】:

我在根据父子排序列表时遇到问题。

这是C# dotnetfiddle.net上提供的代码

这是Section Object的模型:

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 = 如果有,则父节组必须在此组之上。

【问题讨论】:

  • 您可以在预期结果中添加列名吗?
  • @PrasadTelkikar 我没有投反对票,但问题并不清楚,而且小提琴包含太多不必要的细节。
  • @ilkerkaran 是的,对不起,我现在就编辑
  • @TreeGround 看来你只是想按id下单,你可以用.OrderBy( x =&gt; x.Id)我想
  • @PrasadTelkikar 我认为最好发布一些现场内容而不是试图以书面形式解释,因为解释起来并不那么简单。

标签: c# arrays linq sorting


【解决方案1】:

这就是我现在解决它的方法......如果其他人将来需要的话。

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

随意改进或使它更优雅:)

【讨论】:

  • 除非内容已经在答案中,否则不要链接到外部网站。
  • 另外,像这样调用new Random().Next(1000) 会给你重复的值。始终使用 Random 的单个实例(每个线程)。
  • IdSectionIDParentID 如何相互关联?如果我知道我可能会给你一个三班轮。
  • @Enigmativity hi,sectionid和parentid是相关的,id不重要,rowid应该按升序排列。
  • SectionIDParentID 有什么关系? 这不像正常的父/子关系 - 每边有两个 `137。
猜你喜欢
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多