在List <T> .AddRange中使用Linq查询有条件地将元素从一个列表添加到另一个列表

ini*_*iki 6 c# linq

我有一个List<String>和两个List<CustomObject>.
我想要组合两个,List<CustomObject>但仅当第二个List<CustomObject>属性未包含在内时List<String>.

所以,想要做这样的事情:

resultSet1.AddRange(resultSet2.Select(x => !names.Contains(x.City)).ToList());
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?

Ant*_*ram 13

Select当你应该使用时,你会误用Where.

resultSet1.AddRange(resultSet2.Where(x => !names.Contains(x.City));
Run Code Online (Sandbox Code Playgroud)

Select是一种投影方法.它需要一个序列并选择它,有时选择整个项目,单个属性,或将其完全投射到其他东西.

Where是一种过滤方法.它接受一个序列并对其应用谓词,只产生传递谓词的元素.

(在您的示例中,通过使用Select,您有效地尝试将列表添加bool到列表中CustomObject,但这不会起作用.)


没有解决手头的具体错误,这里有一些需要考虑的其他想法.

这是一种HashSet<string>可能有益的情况names,特别是如果names非常大的话.Contains在a上HashSet<T>是O(1)复杂度,而它是O(n)List<T>.但是,HashSet会产生开销,因此如果您有任何疑虑,最好同时测量两者并查看哪个更高效.

还有一件事可能会有所帮助,如果您只需要将一个序列流式传输到另一个序列之后并且不一定需要更改或添加到任一集合,您可以考虑使用UnionConcat操作.

var sequence = resultSet1.Union(resultSet2.Where(x => !names.Contains(x.City)));
var sequence = resultSet1.Concat(resultSet2.Where(x => !names.Contains(x.City)));
Run Code Online (Sandbox Code Playgroud)

两者之间的差异Union将过滤掉结果序列中的任何重复(来自两个输入,而不仅仅是第二个与第一个),Concat不应用重复过滤逻辑,只是简单地将一个序列流传输到另一个序列.输入序列(resultSet1resultSet2)未经修改.