2017-09-06 82 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();

相關問題