在C#中,我有员工对象列表。 员工类是
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
}
在列出的对象中已排序基于 Employee.ID 。我有一个数组的int,它基本上是我想要的列表顶部的Employee.ID,在列表中,顺序必须与数组中的相同。
如果我这样输入 列表:
[
{ID:1,Name:A},
{ID:2,Name:B},
{ID:3,Name:AA},
{ID:4,Name:C},
{ID:5,Name:CD},
.
.
{ID:100,Name:Z}
]
和数组:{2,3,1}
然后我想要输出列表:
[
{ID:2,Name:B},
{ID:3,Name:AA},
{ID:1,Name:A},
{ID:4,Name:C},
{ID:5,Name:CD},
.
.
{ID:100,Name:Z}
]
我已经完成了这个
foreach (int i in a)
{
list = list.OrderBy(x => x.ID != i).ToList();
}
//a is array
//list is List
任何更好的Solution.Thanks提前。
答案 0 :(得分:2)
根据ID
对列表进行排序后,只需迭代数组并移动元素。为此,您需要先删除,然后将项目插入正确的位置。
for(int i = 0; i < myArray.Length; i++)
{
var e = myList.Single(x => x.Id == myArray[i]);
myList.Remove(e);
myList.Insert(i, e);
}
您可能还想使用SingleOrDefault
代替Single
来验证myList
是否包含具有当前ID的元素,例如当您的数组包含[2, 3, 101]
答案 1 :(得分:2)
添加另一个版本。完整的分类可以一次完成:
list = list.OrderBy(e=> {int i =Array.IndexOf(a, e.ID); return i == -1 ? int.MaxValue : i; }).ToList();
其中list
是EmployeeList,a
是indices数组。 (注意,不需要for循环,上面应该进行两种排序)。
在OrderBy
回调中,如果id不在a
内,则返回int.MaxValue将其置于数组内的{(1}}之后)。对于那些返回相同值的元素,a.Length
应保持枚举(列表)的原始顺序。
PS,如果你想首先按OrderBy
内的索引进行排序,其余的就是ids(不一定是原始顺序),你可以使用以下(只要a.Length +最大ID&lt; int.MaxValue):a
答案 2 :(得分:1)
这是一种在纯LINQ中执行此操作的方法,无需更改原始序列。
分成几步,看看发生了什么。
public static void Main()
{
var employeeList = new List<Employee>()
{
new Employee(){ ID= 1,Name= "A"},
new Employee() { ID= 2,Name= "B"},
new Employee() { ID= 3,Name= "AA"},
new Employee() { ID= 4,Name= "C"},
new Employee() { ID= 5,Name= "CD"},
new Employee() { ID= 100,Name= "Z"}
};
var orderByArray = new int[] { 2, 3, 1, 100, 5, 4 };
var sortPos = orderByArray.Select((i, index) => new { ID = i, SortPos = index });
var joinedList = employeeList.Join(sortPos, e => e.ID, sp => sp.ID, (e, sp) => new { ID = e.ID, Name = e.Name, SortPos = sp.SortPos });
var sortedEmployees = joinedList.OrderBy(e => e.SortPos).Select(e => new Employee { ID = e.ID, Name = e.Name });
}
答案 3 :(得分:1)
使用LINQ尝试此操作:
.Wait()
在ids数组中的Foreach id我们将获取匹配的员工,我们将连接所有在id组件中不存在id的员工。
答案 4 :(得分:1)
我喜欢使用特殊的Comparer
,对我来说似乎更清楚,但代码更多一些。它隐藏了比较器类中的排序的复杂性,然后你可以用它来调用它:
theList.OrderBy(x => x.id, new ListOrderBasedComparer(sortList));
它将根据在实例化时传递给比较器的任何列表进行排序,并将元素放在&#34;已知排序列表中#34;最后。
您当然可以根据自己的特殊需求进行调整。
public class ListOrderBasedComparer: Comparer<int>
{
private List<int> sortList;
public ListOrderBasedComparer(List<int> sortList)
{
// if you want you can make constructor accept arrays and convert it
// (if you find that more convenient)
this.sortList = sortList;
}
public override int Compare(int x, int y)
{
var indexOfX = sortList.FindIndex(a => a == x);
var indexOfY = sortList.FindIndex(a => a == y);
// handle elements not in sortArray : if not in sort array always assume they should be "less than the others" and "equal between them".
if (indexOfX == -1 && indexOfY == -1) return 0;
if (indexOfY == -1) return -1;
if (indexOfX == -1) return 1;
// if elements are in sortArray (FindIndex returned other than -1), use usual comparison of index values
return indexOfX.CompareTo(indexOfY);
}
}
如何使用它的示例,使用Linq:
public class TestCompare
{
public void test ()
{
var myArray = new MyClass[]
{
new MyClass { id = 1, name = "A" },
new MyClass { id = 2, name = "B" },
new MyClass { id = 3, name = "C" },
new MyClass { id = 4, name = "D" },
new MyClass { id = 5, name = "E" },
new MyClass { id = 6, name = "F" },
};
var myArray2 = new MyClass[]
{
new MyClass { id = 1, name = "A" },
new MyClass { id = 2, name = "B" },
new MyClass { id = 0, name = "X" },
new MyClass { id = 3, name = "C" },
new MyClass { id = 4, name = "D" },
new MyClass { id = 23, name = "Z"},
new MyClass { id = 5, name = "E" },
new MyClass { id = 6, name = "F" },
};
var sortList = new List<int> { 2, 3, 1, 4, 5, 6 };
// good order
var mySortedArray = myArray.OrderBy(x => x.id, new ListOrderBasedComparer(sortList)).ToList();
// good order with elem id 0 and 23 at the end
var mySortedArray2 = myArray2.OrderBy(x => x.id, new ListOrderBasedComparer(sortList)).ToList();
}
}
public class MyClass
{
public int id;
public string name;
}