C# 在C语言中,我如何对这个对象列表按哪个项更大排序?

C# 在C语言中,我如何对这个对象列表按哪个项更大排序?,c#,list,collections,C#,List,Collections,我有一个简单的类,名为Team,如下所示: public class Team { public Team ParentTeam; public string Name; } List<Team> list = new List() { teamA, teamB, teamC, teamD }; 因此,它有一个名称和对另一个团队(即其父团队)的引用 我现在有了一个从一个函数中得到的团队列表 List<Team> list = GetTeamsLi

我有一个简单的类,名为Team,如下所示:

public class Team
{
     public Team ParentTeam;
     public string Name;
}
 List<Team> list = new List() { teamA, teamB, teamC, teamD };
因此,它有一个名称和对另一个团队(即其父团队)的引用

我现在有了一个从一个函数中得到的团队列表

List<Team> list = GetTeamsList();
但是GetTeamsList函数以任意随机顺序返回团队。例如,它可能会返回以下列表:

 var teamA = GetTeamA();
 var teamB = GetTeamB();
 var teamC = GetTeamC();
 var teamD = GetTeamD();

 List<Team> list = new List() { teamD, teamA, teamB, teamC };
我需要重新排列此列表,使其看起来像这样:

public class Team
{
     public Team ParentTeam;
     public string Name;
}
 List<Team> list = new List() { teamA, teamB, teamC, teamD };
如何根据团队层次结构将列表重新排序为正确的顺序?

这是我的建议:

public class Team
    {
        public Team ParentTeam;
        public string Name;

        int Level
        {
            get
            {
                int i = 0;
                Team p = this.ParentTeam;
                while (p != null)
                {
                    i++;
                    p = p.ParentTeam;
                }
                return i;
            }
        }

        static IEnumerable<Team> Sort(IEnumerable<Team> list)
        {
            return list.OrderBy(o => o.Level);
        }
    }
当然,如果有级别相同的团队,您可以使用其他标准对其进行排序

这是我的建议:

public class Team
    {
        public Team ParentTeam;
        public string Name;

        int Level
        {
            get
            {
                int i = 0;
                Team p = this.ParentTeam;
                while (p != null)
                {
                    i++;
                    p = p.ParentTeam;
                }
                return i;
            }
        }

        static IEnumerable<Team> Sort(IEnumerable<Team> list)
        {
            return list.OrderBy(o => o.Level);
        }
    }
当然,如果有级别相同的团队,您可以使用其他标准对其进行排序

这应该有效:

static IEnumerable<Team> GetOrdered(IEnumerable<Team> teams)
{
    var set = teams as HashSet<Team> ?? new HashSet<Team>(teams);
    var current = teams.First(t => t.Parent == null);

    while (set.Count > 1)
    {
        yield return current;
        set.Remove(current);
        current = set.First(t => t.Parent == current);
    }

    yield return set.Single();
}
这将为您提供相反的顺序,因此您应该致电Reverse以获取所需的顺序。

这应该可以:

static IEnumerable<Team> GetOrdered(IEnumerable<Team> teams)
{
    var set = teams as HashSet<Team> ?? new HashSet<Team>(teams);
    var current = teams.First(t => t.Parent == null);

    while (set.Count > 1)
    {
        yield return current;
        set.Remove(current);
        current = set.First(t => t.Parent == current);
    }

    yield return set.Single();
}

这将为您提供相反的顺序,因此您应该调用Reverse来获取您所请求的顺序。

我们可以找到null团队的上升点,定义一个扩展

    public static IEnumerable<Team> FindAscendants(this IEnumerable<Team> l, Team from)
    {
        Team t = l.FirstOrDefault(x => 
            (x.ParentTeam?.Name ?? "").Equals(from?.Name ?? ""));
        return new List<Team>() { t }.Concat(t != null ?
            l.FindAscendants(t) : Enumerable.Empty<Team>());
    }
编辑

具有收益率回报的扩展的替代版本

适当填充,如下所示

            team.ParentTeam = list.Last();
            list.Last().ChildTeam = team;
启用立即重新排序的步骤

        DateTime start = DateTime.Now;
        var res = list.OrderByChild(); //list.FindDescendandOptimized(null);
        list = res.ToList();
        DateTime end = DateTime.Now;
        Console.WriteLine("Reordered List");
有直接联系

    public static IEnumerable<Team> OrderByChild(this List<Team> l)
    {
        int count = l.Count;
        Team start = l.First(x => x.ParentTeam == null);
        Team[] res = new Team[count];
        res[count - 1] = start;
        for (int i = count - 2; i >= 0; i--)
        {
            start = start.ChildTeam;
            res[i] = start;
        }
        return res;
    }

我们可以找到null团队的优势,定义一个扩展

    public static IEnumerable<Team> FindAscendants(this IEnumerable<Team> l, Team from)
    {
        Team t = l.FirstOrDefault(x => 
            (x.ParentTeam?.Name ?? "").Equals(from?.Name ?? ""));
        return new List<Team>() { t }.Concat(t != null ?
            l.FindAscendants(t) : Enumerable.Empty<Team>());
    }
编辑

具有收益率回报的扩展的替代版本

适当填充,如下所示

            team.ParentTeam = list.Last();
            list.Last().ChildTeam = team;
启用立即重新排序的步骤

        DateTime start = DateTime.Now;
        var res = list.OrderByChild(); //list.FindDescendandOptimized(null);
        list = res.ToList();
        DateTime end = DateTime.Now;
        Console.WriteLine("Reordered List");
有直接联系

    public static IEnumerable<Team> OrderByChild(this List<Team> l)
    {
        int count = l.Count;
        Team start = l.First(x => x.ParentTeam == null);
        Team[] res = new Team[count];
        res[count - 1] = start;
        for (int i = count - 2; i >= 0; i--)
        {
            start = start.ChildTeam;
            res[i] = start;
        }
        return res;
    }

到目前为止给出的几个解决方案是正确的,并且所有这些解决方案在团队数量上至少都是二次的;随着团队数量的增加,他们将变得效率低下

这里有一个解决方案,与目前的一些其他解决方案相比,它1是线性的,2是较短的,3是更容易理解的:

static IEnumerable<Team> SortTeams(IEnumerable<Team> teams)
{
  var lookup = teams.ToDictionary(t => t.ParentTeam ?? new Team());
  var current = teams.Single(t => t.ParentTeam == null);
  do
    yield return current;
  while (lookup.TryGetValue(current, out current));
}

虚拟团队的存在是因为字典不允许密钥为空。

到目前为止给出的几个解决方案是正确的,并且所有这些解决方案在团队数量上至少都是二次的;随着团队数量的增加,他们将变得效率低下

这里有一个解决方案,与目前的一些其他解决方案相比,它1是线性的,2是较短的,3是更容易理解的:

static IEnumerable<Team> SortTeams(IEnumerable<Team> teams)
{
  var lookup = teams.ToDictionary(t => t.ParentTeam ?? new Team());
  var current = teams.Single(t => t.ParentTeam == null);
  do
    yield return current;
  while (lookup.TryGetValue(current, out current));
}

虚拟团队之所以存在,是因为字典不允许键为null。

建议:使用.Firstt=>,而不是.Wheret=>…首先,使用.Firstt=>。。。两个地方。在第一行中,使用var set=teams作为HashSet??新的HashSetteams@JeppeStigNielsen你说得对!谢谢,更新代码。我总是忘记First、Last、Count等,有一个带谓词的重载。。。两个地方。在第一行中,使用var set=teams作为HashSet??新的HashSetteams@JeppeStigNielsen你说得对!谢谢,更新代码。我总是忘记First、Last、Count等,它们都有一个重载,这个重载使用谓词。您能提供GetTeamsList的代码,以及初始化具有完整层次结构的团队的C可编译代码吗?我希望能够复制、粘贴和运行您的代码以查看您的问题。两个团队是否有过相同的父团队?如果是这样,那么有没有办法决定哪一个先到?因为如果没有,那么你就没有正确的顺序。您正在描述一个晶格,而晶格不一定具有总的顺序。使用拓扑排序查找晶格的可能顺序。使用新的限制,您有一个链表,其中下一个指针称为父节点,头节点是最深的团队,顶部团队是尾部节点。您能否提供GetTeamsList的代码以及初始化具有完整层次结构的团队的C可编译代码?我希望能够复制、粘贴和运行您的代码以查看您的问题。两个团队是否有过相同的父团队?如果是这样,那么有没有办法决定哪一个先到?因为如果没有,那么你就没有正确的顺序。您正在描述一个晶格,而晶格不一定具有总的顺序。您可以使用拓扑排序来查找晶格的可能顺序。使用新的限制,您将有一个链接列表,其中下一个指针称为父节点,头节点是最深的团队,顶部团队是尾部节点。