我有两个清单:
var list1 = new List<string> { "A", "A", "B", "C" };
var list2 = new List<string> { "A", "B" };
我想列一个清单
var result = new[] { "A", "C" };
这里的列表是list1
中所有从list2
中删除的元素,我认为没有Linq扩展方法,因为Except
删除了重复的元素。
非线性的方法是:
var tempList = list1.ToList();
foreach(var item in list2)
{
tempList.Remove(item);
}
但我想知道是否有一个Linq扩展方法我可能错过了。
编辑:
因为可能没有,所以我做了一个扩展方法。
public static class LinqExtensions
{
public static IEnumerable<T> RemoveRange<T>(this IEnumerable<T> source, IEnumerable<T> second)
{
var tempList = source.ToList();
foreach(var item in second)
{
tempList.Remove(item);
}
return tempList;
}
public static IEnumerable<TFirst> RemoveMany<TFirst, TSecond>(this IEnumerable<TFirst> source, IEnumerable<TSecond> second, Func<TSecond, IEnumerable<TFirst>> selector)
{
var tempList = source.ToList();
foreach(var item in second.SelectMany(selector))
{
tempList.Remove(item);
}
return tempList;
}
}
用法:
list1.RemoveRange(list2)
3条答案
按热度按时间b0zn9rqh1#
看一下你的例子,我认为你的意思是“从list1中删除list2中的所有元素”:
kzmpq1sx2#
不是LINQ,而是一行代码:
顺便说一句...如果
List<int>
有类似AddRange
的东西,但是同时删除一堆项目,那就太好了。nzrxty8p3#
如果您不关心结果元素出现的顺序,可以使用LINQ的
GroupBy
:这是一个demo on ideone。
我必须承认,您的解决方案比我的简单得多,所以它应该被看作是一种纯粹的好奇心,一种证明这也可以用LINQ来完成的方法。
下面是它的工作原理:对于来自第一个列表的每个元素,我们添加具有
1
的键-值对;对于第二个列表中的每一个元素,我们添加一个键值对-1
,然后我们按照键对所有元素进行分组,将它们的1和负的相加,并产生与总和一样多的键,确保当结果为负时我们不选择任何东西。