我有以下情况:
列表1有20个TItem类型的项目,列表2有5个相同类型的项目。列表1已包含列表2中的项目,但处于不同的状态。我想用列表2中的项目覆盖列表1中的5个项目。
我认为联接可能有效,但我想覆盖列表1中的项目,而不是将它们连接在一起并且有重复项。
有一个唯一的键可用于查找列表1中要覆盖哪些项,键的类型为int
答案 0 :(得分:2)
你可以使用内置的Linq .Except()但是它想要一个IEqualityComparer,所以使用。a fluid version的.Except()代替。
假设一个对象带有一个整数键,如你所示:
public class Item
{
public int Key { get; set; }
public int Value { get; set; }
public override string ToString()
{
return String.Format("{{{0}:{1}}}", Key, Value);
}
}
原始的对象列表可以与更改的对象合并,如下所示:
IEnumerable<Item> original = new[] { 1, 2, 3, 4, 5 }.Select(x => new Item
{
Key = x,
Value = x
});
IEnumerable<Item> changed = new[] { 2, 3, 5 }.Select(x => new Item
{
Key = x,
Value = x * x
});
IEnumerable<Item> result = original.Except(changed, x => x.Key).Concat(changed);
result.ForEach(Console.WriteLine);
输出:
{1:1}
{4:4}
{2:4}
{3:9}
{5:25}
答案 1 :(得分:1)
LINQ不用于对底层数据源执行实际修改;它严格来说是一种查询语言。当然,您可以在List2
上List1
进行外部联接,如果不是空,则选择List2
的实体,如果是List1
的实体,则选择IEnumerable<>
这会给你一个ToList()
的结果;它实际上不会修改集合。您可以对结果执行List1
并将其分配给List1
,但这会更改引用;我不知道这是否会影响你申请的其余部分。
从字面上理解您的问题,因为您希望将List2
中的项目替换为for
中的项目(如果存在),那么您必须在List1
中手动执行此操作循环遍历List2
,检查List1
中是否存在相应的条目,并使用List2
中的{{1}}条目替换{{1}}条目。
答案 2 :(得分:1)
正如亚当所说,LINQ是关于查询的。但是,您可以使用Enumerable.Union
以正确的方式创建新集合。你需要创建一个合适的IEqualityComparer
- 拥有UnionBy
会很高兴。 (也许是MoreLINQ的另一个?)
基本上:
var list3 = list2.Union(list1, keyComparer);
其中keyComparer
是比较两个键的实现。 MiscUtil包含ProjectionEqualityComparer
,这会使这更容易。
或者,您可以在连接后使用MoreLINQ中的DistinctBy
:
var list3 = list2.Concat(list1).DistinctBy(item => item.Key);
答案 3 :(得分:0)
这是GroupJoin的解决方案。
List<string> source = new List<string>() { "1", "22", "333" };
List<string> modifications = new List<string>() { "4", "555"};
//alternate implementation
//List<string> result = source.GroupJoin(
// modifications,
// s => s.Length,
// m => m.Length,
// (s, g) => g.Any() ? g.First() : s
//).ToList();
List<string> result =
(
from s in source
join m in modifications
on s.Length equals m.Length into g
select g.Any() ? g.First() : s
).ToList();
foreach (string s in result)
Console.WriteLine(s);
嗯,我正在使用的可重用扩展方法怎么样:
public static IEnumerable<T> UnionBy<T, U>
(
this IEnumerable<T> source,
IEnumerable<T> otherSource,
Func<T, U> selector
)
{
return source.GroupJoin(
otherSource,
selector,
selector,
(s, g) => g.Any() ? g.First() : s
);
}
由以下人员召集:
List<string> result = source
.UnionBy(modifications, s => s.Length)
.ToList();