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

时间:2011-10-19 15:23:17

标签: c# linq

我有一个List<String>和两个List<CustomObject> 我想合并两个List<CustomObject>,但前提是List<CustomObject>中不包含第二个List<String>属性。

所以,想做这样的事情:

resultSet1.AddRange(resultSet2.Select(x => !names.Contains(x.City)).ToList());

我在这里缺少什么?

1 个答案:

答案 0 :(得分:13)

您应该使用Select时误导Where

resultSet1.AddRange(resultSet2.Where(x => !names.Contains(x.City));

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

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

(在您的示例中,使用Select,您有效地尝试将bool列表添加到CustomObject的列表中,但这不会起作用。)< / p>


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

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

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

var sequence = resultSet1.Union(resultSet2.Where(x => !names.Contains(x.City)));
var sequence = resultSet1.Concat(resultSet2.Where(x => !names.Contains(x.City)));

两者的区别在于Union将过滤掉结果序列中的任何重复项(来自两个输入,而不仅仅是第二个与第一个相对),Concat不应用重复过滤逻辑和简单地将一个序列流到另一个序列。输入序列(resultSet1resultSet2)未经修改。