是否有同时Take
和Remove
的linq方法。
假设我想将前五个元素从一个列表移动到另一个列表。我确信我可以用几个linq语句来做到这一点,但有时我发现我已经重新发明了一个已经存在的方法。
现在有这样的方法吗? (如果不是我可以做到。)
答案 0 :(得分:4)
不,没有。 LINQ代表语言集成查询,它的所有方法都用于导航和检查现有集合。它没有任何改变集合的方法。
但是,您可以使用List<T>
类的某些方法。尽管如此,还没有单一的方法。这是一个最小的解决方案:
list1.AddRange(list2.Take(5));
list2.RemoveRange(0, 5);
但如果您真的想要,可以将其包装在自定义扩展方法中:
public static class MyListExtensions {
public static IEnumerable<T> TakeAndRemove<T>(this List<T> list, int count) {
foreach(var n in list.Take(count))
yield return n;
source.RemoveRange(0, count);
}
}
list1.AddRange(list2.TakeAndRemove(5));
答案 1 :(得分:2)
是的,没有Linq方法在单个语句中执行此操作。我有最小的解决方案是这样的
List<string> one = new List<string>() { "1", "2", "3", "4", "5", "6", "7" };
List<string> two = new List<string>() { "1", "2", "3", "4", "5", "6", "7" };
two.AddRange(one.Take(5));
one.RemoveRange(0, 5);
答案 2 :(得分:1)
不,没有。你应该创建自己的。我不确定在同一个动作中读取和修改列表是否是一个好主意。
答案 3 :(得分:1)
LINQ不能有这样的方法,因为它永远不会改变传递给它的集合。但是,您可以使用LINQ为您完成大部分工作。
考虑一个示例:假设您需要从listA
删除所有通过某个条件的项目,并将其添加到listB
。您可以将LINQ分区listA
放入要保留的部分和要删除的部分,然后将所有已删除的项目添加到listB
。以下是如何做到这一点:
// Let's say you want to remove all items with name starting in "X"
// The dictionary will contain two keys - true and false
// Items to keep will be under "true"; items to remove will be under "false"
var d = listA
.GroupBy(item => !item.Name.StartsWith("X"))
.ToDictionary(p => p.Key, p => p.ToList());
// Reassign the list of items that you keep to listA
listA = d[true];
// Add items from the list of items to be removed to listB
listB.AddRange(d[false]);
答案 4 :(得分:1)
没有现成的LINQ方法可以做到这一点,但似乎你可以在List<T>
之上构建一个。基本结构是有一个谓词,它删除值,函数返回被删除的值集。
static List<T> RemoveAndReturn<T>(this List<T> list, Predicate<T> predicate) {
var removed = new List<T>();
int i = 0;
while (i < list.Count) {
var current = list[i];
if (predicate(current)) {
removed.Add(current);
list.RemoveAt(i);
} else {
i++;
}
}
return removed;
}
请注意,这并非真正符合LINQ的精神,因为第一部分执行的是迅速而不是延迟的方式。这是恕我直言,以避免意外双重删除
使用此方法,您可以执行类似LINQ的查询,删除和操作。但最好将它们称为流利而不是LINQ