将满足条件的列表元素移动到列表顶部

时间:2016-11-30 15:55:05

标签: c#

我想将特定号码移到此列表的顶部。

int numberToBeMovedOnTop = 4;
List<int> lst = new List<int>(){1, 2, 3, 4, 5, 5, 4, 7, 9, 4, 2, 1};
List<int> lstOdd = lst.FindAll(l => l == numberToBeMovedOnTop);
lstOdd.AddRange(lst.FindAll(l => l != numberToBeMovedOnTop));

numberToBeMovedOnTop是变量。

这给了我想要的结果,但对此更好的解决方案?我可以迭代列表一次并将numberToBeMovedOnTop的第一次出现与第一个元素交换,第二次出现numberToBeMovedOnTop与第二个元素交换,依此类推。但是这可以通过一些内置的C#函数来完成,而无需迭代列表两次吗?

3 个答案:

答案 0 :(得分:12)

您可以使用LINQ:

List<int> lstOdd = lst.OrderByDescending(i => i == numberToBeMovedOnTop).ToList();

为什么OrderByDescending?因为比较返回booltrue高于false。你也可以使用:

List<int> lstOdd = lst.OrderBy(i => i == numberToBeMovedOnTop ? 0 : 1).ToList();

请注意,这是有效的,因为OrderByOrderByDescending正在执行stable sort。这意味着原始订单仍然适用于所有相同的项目。

对于它的价值,这里有一个扩展方法,适用于任何类型和谓词,并且效率更高一点:

public static List<T> PrependAll<T>(this List<T> list, Func<T, bool> predicate)
{
    var returnList = new List<T>();
    var listNonMatch = new List<T>();
    foreach (T item in list)
    {
        if (predicate(item))
            returnList.Add(item);
        else
            listNonMatch.Add(item);
    }
    returnList.AddRange(listNonMatch);
    return returnList;
}

用法:List<int> lstOdd = lst.PrependAll(i => i == numberToBeMovedOnTop);

答案 1 :(得分:2)

除了使用linq之外,如果没有linq

,这样做可能同样有效/可理解
var listToAdd = new List<int>();
var listOdd = new List<int>();
for(int i = 0; i < lst.Count; i++)
{
    if(lst[i] == numberToBeMovedOnTop)
    {
        listToAdd.Add(numberToBeMovedOnTop);
    }
    else
    {
        listOdd.Add(lst[i]);
    }

}
listOdd.AddRange(listToAdd);

跟踪您已删除的内容,然后再添加

答案 2 :(得分:0)

按谓词分组,然后联合?

        var nums = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        var grp = nums.GroupBy(x => x % 2 == 0).ToList();
        var changed = grp[0].Union(grp[1]).ToList();