2017-09-06 76 views
2

在C#中,我有Employee对象列表员工类是c#:将ID为数组的列表移动到列表顶部

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} 
] 

和Array:{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 

任何更好的解决方案。提前感谢。

+0

可能重复的[C#列表<>按x然后y排序](https://stackoverflow.com/questions/289010/c-sharp-list-sort-by-x-then-y) –

+0

虽然我已经标记为重复,这是你根据你的问题寻找的那种东西。 https://stackoverflow.com/questions/289010/c-sharp-list-sort-by-x-then-y –

+0

这不是这个问题的重复。没有可用于排序数组的*属性*,而是另一个数组*。 – HimBromBeere

回答

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]

+0

我同意@HimBromBeere。另外,您应该考虑这个列表不包含该项目的事实。 – Tunahan

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 }); 

    } 
1

试试这个使用LINQ:

List<Employee> employees = ... 
int[] ids = ... 
var orderEmployees = ids.Select(id => employees.Single(employee => employee.ID == id)) 
     .Concat(employees.Where(employee => !ids.Contains(employee.ID)).ToList(); 

在ids数组的foreach ID,我们将抓住匹配的员工,我们将Concat的它自己的ID不ids数组存在的所有员工。

1

我喜欢使用特殊的Comparer,对我来说这似乎更清楚,但代码更多一点。它隐藏排序的比较器类的复杂性,那么你可以只用把它叫做:

theList.OrderBy(x => x.id, new ListOrderBasedComparer(sortList));

将根据实例化时传递到比较器的任何列表进行排序,并把元素不在最后的“已知排序列表”中。

您当然可以根据您的特殊需求进行调整。关于如何使用它,使用LINQ

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); 
    } 
} 

例子:

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; 
} 
2

要添加其他版本的组合。完整的分类可以一气呵成完成:

list = list.OrderBy(e=> {int i =Array.IndexOf(a, e.ID); return i == -1 ? int.MaxValue : i; }).ToList(); 

其中list是EmployeeList的和a指数阵列。 (注意,for循环不需要,上面的代码应该可以同时进行分类)。

OrderBy回调中,如果ID不在a之内,则返回int.MaxValue以将其置于数组内(a.Length也可以)。 OrderBy应该为那些返回相同值的元素维护枚举(列表)的原始顺序。如果要首先按a内的索引进行排序,其余的依次在ID(不一定是原始顺序),则可以使用以下内容(只要a.Length +最大ID < int.MaxValue) :list = list.OrderBy(e=> {int i =Array.IndexOf(a, e.ID); return i == -1 ? a.Length + e.ID : i; }).ToList();

相关问题