我想将特定号码移到此列表的顶部。
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#函数来完成,而无需迭代列表两次吗?
答案 0 :(得分:12)
您可以使用LINQ:
List<int> lstOdd = lst.OrderByDescending(i => i == numberToBeMovedOnTop).ToList();
为什么OrderByDescending
?因为比较返回bool
而true
高于false
。你也可以使用:
List<int> lstOdd = lst.OrderBy(i => i == numberToBeMovedOnTop ? 0 : 1).ToList();
请注意,这是有效的,因为OrderBy
和OrderByDescending
正在执行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();