C# 在C语言中,我如何对这个对象列表按哪个项更大排序?
我有一个简单的类,名为Team,如下所示: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
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可编译代码?我希望能够复制、粘贴和运行您的代码以查看您的问题。两个团队是否有过相同的父团队?如果是这样,那么有没有办法决定哪一个先到?因为如果没有,那么你就没有正确的顺序。您正在描述一个晶格,而晶格不一定具有总的顺序。您可以使用拓扑排序来查找晶格的可能顺序。使用新的限制,您将有一个链接列表,其中下一个指针称为父节点,头节点是最深的团队,顶部团队是尾部节点。