c#:将ID在数组中的元素移动到列表顶部

时间:2017-09-06 07:12:25

标签: c# linq

在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提前。

5 个答案:

答案 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;
}