根据多个参数交换列表项
Swap list item according to multiple parameters
我有一个如下所示的列表。我想根据我指定的规则对这个列表进行排序。如果有一个列表元素附加到的元素,它必须在前排。
例如,由于 ID 为 2 的记录的 RequiredCourse 字段为 3,因此 ID 为 3 的元素必须位于 ID 为 2 的元素之前。为此,我创建了一个 swap 方法,如下所示。但是 ID 为 3 的记录依赖于 4,我无法正确创建排序。此外,它取决于 ID 为 8 及以下的 10。但是 9 没有连接到任何东西。由于我更改了 id 为 8 和 10 的记录的位置,所以 8 在 9 之后。
示例输出应如下所示:
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
list = list.OrderBy(i => i.Id).ThenBy(i => i.RequiredCourse).ToList();
var copy = new List<Course>(list);
for (int i = 0; i < copy.Count; i++)
{
if (!string.IsNullOrEmpty(copy[i].RequiredCourse) && Int32.Parse(copy[i].RequiredCourse) > copy[i].Id)
{
var index = list.FindIndex(k => k.Id == Int32.Parse(copy[i].RequiredCourse));
if (index > -1)
{
var temp = list[i];
list[i] = list[index];
list[index] = temp;
}
}
}
使用上述代码的输出有缺陷
1
3 4
4
2 3
5
6
7
10
9
8 10
预期输出
1
4
3 4
2 3
5
6
7
10
8 10
9
问题是您想要“4 - ''”下方的项目“2 - 3”。我确信有一种方法可以改进我所做的,但这里是 1.0 版:
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
// isolating items with RequiredCourse
var withRequired = (
from o in list
where !string.IsNullOrWhiteSpace(o.RequiredCourse)
select o
).ToList();
list = list.Except(withRequired).ToList();
// First I arrange the items without "RequiredCourse" with their respective ones.
for (var i = 0; i < list.Count; i++)
{
var primary = list[i];
var parents =
withRequired
.Where(o => o.RequiredCourse == primary.Id.ToString())
.OrderBy(o => o.Id)
.ToList();
var children = (
from o in withRequired.Except(parents)
join o2 in parents
on o.Id.ToString() equals o2.RequiredCourse
into grp
from o3 in grp
orderby o3.Id descending
select o3
).ToList();
if (!parents.Any())
{
continue;
}
i++;
foreach (var p in parents)
{
list.Insert(i++, p);
foreach (var c in children.Where(o => p.Id.ToString() == o.RequiredCourse))
{
list.Insert(i++, c);
}
}
}
// retrieving items that only link to items that have RequiredCourse
var childOfChildren = withRequired.Except(list).ToList();
// Then I arrange items with RequiredCourses that are linked to other items with RequiredCourses.
for (var i = 0; i < list.Count; i++)
{
var primary = list[i];
var children = (
from o in childOfChildren
where primary.Id.ToString() == o.RequiredCourse
orderby o.Id descending
select o
).ToList();
if (!children.Any())
{
continue;
}
i++;
list.InsertRange(i, children);
}
// CONSOLE APPLICATION PART
foreach (var o in list)
{
if (string.IsNullOrEmpty(o.RequiredCourse))
{
o.RequiredCourse = "-";
}
Console.WriteLine($"Course: {o.Id} - {o.RequiredCourse}");
}
我觉得这很容易理解。
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
var output = new List<Course>();
var toProcess = new SortedDictionary<int, Course>(list.ToDictionary(c => c.Id));
var pendingAdd = new Stack<Course>();
while (toProcess.Count > 0)
{
Course currentCourse = toProcess.First().Value;
if (string.IsNullOrEmpty(currentCourse.RequiredCourse))
{
// Course has no dependency, process it.
output.Add(currentCourse);
toProcess.Remove(currentCourse.Id);
}
else
{
int courseId = currentCourse.Id;
// Course has dependency. Trace down linked courses.
while (toProcess.ContainsKey(courseId) && !string.IsNullOrEmpty(toProcess[courseId].RequiredCourse))
{
pendingAdd.Push(toProcess[courseId]);
courseId = int.Parse(toProcess[courseId].RequiredCourse);
}
// dont forget to add the "top-level" course for the dependency chain
pendingAdd.Push(toProcess[courseId]);
// Add in reverse depdency order using Stack
while (pendingAdd.Count > 0)
{
var course = pendingAdd.Pop();
output.Add(course);
toProcess.Remove(course.Id);
}
}
}
您的通缉名单在output
。
可以通过回归来完成,示例代码未针对其他情况进行测试。仅针对给定数据进行测试。
public static void Main()
{
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
list = list.OrderBy(i => i.Id).ThenBy(i => i.RequiredCourse).ToList();
var copy = new List<Course>();
foreach(var tt in list)
{
//Console.WriteLine(tt.Id + " " + tt.RequiredCourse);
populateParent(list,ref copy, tt);
if(!copy.Any(p => p.Id == tt.Id))
copy.Add(tt);
}
foreach(var tt in copy)
{
Console.WriteLine(tt.Id + " " + tt.RequiredCourse);
}
}
public static Course populateParent(List<Course> inputList,ref List<Course> outputList, Course current)
{
if(string.IsNullOrWhiteSpace(current.RequiredCourse))
{
if(!outputList.Any(p => p.Id == current.Id))
outputList.Add(current);
return current;
}
else
{
var tt = inputList.First(p => current.RequiredCourse != null && p.Id == int.Parse(current.RequiredCourse) );
var parent = populateParent(inputList,ref outputList,tt);
if(!outputList.Any(p => p.Id == parent.Id))
outputList.Add(parent);
if(!outputList.Any(p => p.Id == tt.Id))
outputList.Add(tt);
return tt;
}
}
我有一个如下所示的列表。我想根据我指定的规则对这个列表进行排序。如果有一个列表元素附加到的元素,它必须在前排。
例如,由于 ID 为 2 的记录的 RequiredCourse 字段为 3,因此 ID 为 3 的元素必须位于 ID 为 2 的元素之前。为此,我创建了一个 swap 方法,如下所示。但是 ID 为 3 的记录依赖于 4,我无法正确创建排序。此外,它取决于 ID 为 8 及以下的 10。但是 9 没有连接到任何东西。由于我更改了 id 为 8 和 10 的记录的位置,所以 8 在 9 之后。
示例输出应如下所示:
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
list = list.OrderBy(i => i.Id).ThenBy(i => i.RequiredCourse).ToList();
var copy = new List<Course>(list);
for (int i = 0; i < copy.Count; i++)
{
if (!string.IsNullOrEmpty(copy[i].RequiredCourse) && Int32.Parse(copy[i].RequiredCourse) > copy[i].Id)
{
var index = list.FindIndex(k => k.Id == Int32.Parse(copy[i].RequiredCourse));
if (index > -1)
{
var temp = list[i];
list[i] = list[index];
list[index] = temp;
}
}
}
使用上述代码的输出有缺陷
1
3 4
4
2 3
5
6
7
10
9
8 10
预期输出
1
4
3 4
2 3
5
6
7
10
8 10
9
问题是您想要“4 - ''”下方的项目“2 - 3”。我确信有一种方法可以改进我所做的,但这里是 1.0 版:
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
// isolating items with RequiredCourse
var withRequired = (
from o in list
where !string.IsNullOrWhiteSpace(o.RequiredCourse)
select o
).ToList();
list = list.Except(withRequired).ToList();
// First I arrange the items without "RequiredCourse" with their respective ones.
for (var i = 0; i < list.Count; i++)
{
var primary = list[i];
var parents =
withRequired
.Where(o => o.RequiredCourse == primary.Id.ToString())
.OrderBy(o => o.Id)
.ToList();
var children = (
from o in withRequired.Except(parents)
join o2 in parents
on o.Id.ToString() equals o2.RequiredCourse
into grp
from o3 in grp
orderby o3.Id descending
select o3
).ToList();
if (!parents.Any())
{
continue;
}
i++;
foreach (var p in parents)
{
list.Insert(i++, p);
foreach (var c in children.Where(o => p.Id.ToString() == o.RequiredCourse))
{
list.Insert(i++, c);
}
}
}
// retrieving items that only link to items that have RequiredCourse
var childOfChildren = withRequired.Except(list).ToList();
// Then I arrange items with RequiredCourses that are linked to other items with RequiredCourses.
for (var i = 0; i < list.Count; i++)
{
var primary = list[i];
var children = (
from o in childOfChildren
where primary.Id.ToString() == o.RequiredCourse
orderby o.Id descending
select o
).ToList();
if (!children.Any())
{
continue;
}
i++;
list.InsertRange(i, children);
}
// CONSOLE APPLICATION PART
foreach (var o in list)
{
if (string.IsNullOrEmpty(o.RequiredCourse))
{
o.RequiredCourse = "-";
}
Console.WriteLine($"Course: {o.Id} - {o.RequiredCourse}");
}
我觉得这很容易理解。
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
var output = new List<Course>();
var toProcess = new SortedDictionary<int, Course>(list.ToDictionary(c => c.Id));
var pendingAdd = new Stack<Course>();
while (toProcess.Count > 0)
{
Course currentCourse = toProcess.First().Value;
if (string.IsNullOrEmpty(currentCourse.RequiredCourse))
{
// Course has no dependency, process it.
output.Add(currentCourse);
toProcess.Remove(currentCourse.Id);
}
else
{
int courseId = currentCourse.Id;
// Course has dependency. Trace down linked courses.
while (toProcess.ContainsKey(courseId) && !string.IsNullOrEmpty(toProcess[courseId].RequiredCourse))
{
pendingAdd.Push(toProcess[courseId]);
courseId = int.Parse(toProcess[courseId].RequiredCourse);
}
// dont forget to add the "top-level" course for the dependency chain
pendingAdd.Push(toProcess[courseId]);
// Add in reverse depdency order using Stack
while (pendingAdd.Count > 0)
{
var course = pendingAdd.Pop();
output.Add(course);
toProcess.Remove(course.Id);
}
}
}
您的通缉名单在output
。
可以通过回归来完成,示例代码未针对其他情况进行测试。仅针对给定数据进行测试。
public static void Main()
{
var list = new List<Course>();
list.Add(new Course { Id = 1 });
list.Add(new Course { Id = 2, RequiredCourse = "3" });
list.Add(new Course { Id = 3, RequiredCourse = "4" });
list.Add(new Course { Id = 4 });
list.Add(new Course { Id = 5 });
list.Add(new Course { Id = 6 });
list.Add(new Course { Id = 7 });
list.Add(new Course { Id = 8, RequiredCourse = "10" });
list.Add(new Course { Id = 9 });
list.Add(new Course { Id = 10 });
list = list.OrderBy(i => i.Id).ThenBy(i => i.RequiredCourse).ToList();
var copy = new List<Course>();
foreach(var tt in list)
{
//Console.WriteLine(tt.Id + " " + tt.RequiredCourse);
populateParent(list,ref copy, tt);
if(!copy.Any(p => p.Id == tt.Id))
copy.Add(tt);
}
foreach(var tt in copy)
{
Console.WriteLine(tt.Id + " " + tt.RequiredCourse);
}
}
public static Course populateParent(List<Course> inputList,ref List<Course> outputList, Course current)
{
if(string.IsNullOrWhiteSpace(current.RequiredCourse))
{
if(!outputList.Any(p => p.Id == current.Id))
outputList.Add(current);
return current;
}
else
{
var tt = inputList.First(p => current.RequiredCourse != null && p.Id == int.Parse(current.RequiredCourse) );
var parent = populateParent(inputList,ref outputList,tt);
if(!outputList.Any(p => p.Id == parent.Id))
outputList.Add(parent);
if(!outputList.Any(p => p.Id == tt.Id))
outputList.Add(tt);
return tt;
}
}