如何使用 linq 或 moreLinq 比较和合并列表
How to compare and merge lists using linq or moreLinq
我有两个 KeyValuePair 类型的列表。
数值如下
List A
2019-01-01 1
2019-01-02 0
2019-01-03 1
List B
2019-01-01 0
2019-01-03 1
我想合并这两个列表,使其看起来像这样
List C
2019-01-01 0 //item from list B
2019-01-02 0 //item from list A, missing date in List B
2019-01-03 1 //item from list A - items are the same in list A and B
Linq 或 MoreLinq 有没有办法真正做到这一点,即。
- 合并两个列表中的项目
- 如果列表 B 中不存在相同的项目,则使用列表 A 中的项目
- 如果列表 A 中的项目不相等,则用列表 B 中的项目替换它们
我制定了这样的东西。请检查:
var q =
from a in ListA
join b in ListB on a.Dt equals b.Dt into j
from b in j.DefaultIfEmpty()
select new { Date=a.dt, Val = a.val == b?.val ? a.val : (b?.val ?? a.val) };
如果您知道您永远无法将默认 DateTime
作为密钥:
var r = from a in ListA
join b in ListB on a.Key equals b.Key into joined
from b in joined.DefaultIfEmpty()
select b.Key != default(DateTime) ? b : a;
如果您可能有一个默认的 DateTime
然后将键转换为 DateTime?
并再次返回以可靠地检测丢失的大小写:
var r = from a in ListA.Select(kv => new KeyValuePair<DateTime?, int>(kv.Key, kv.Value))
join b in ListB.Select(kv => new KeyValuePair<DateTime?, int>(kv.Key, kv.Value))
on a.Key equals b.Key into joined
from b in joined.DefaultIfEmpty()
select new KeyValuePair<DateTime, int>(b.Key ?? a.Key.GetValueOrDefault(), b.Value);
请注意,在两者中我们都跳过规则 "replace item from list A with item from list B if they are not equal",只使用 "use the item from B if it exists",因为我们必须检查 B 是否存在,如果 B 的值与 A 的值相同,则无关紧要我们仍然使用它。
我可能只是从 A 构建一个字典,然后用 B 的值替换值,除非我真的关心顺序。
请先阅读我对问题的评论。
var result = ListB
.Union(ListA)
.GroupBy(kvp=>kvp.Key)
.Select(grp=> new KeyValuePair<DateTime, int>(grp.Key, grp.Select(v=>v.Value).First()))
.OrderBy(kvp=>kvp.Key);
注意#1:我认为它的效率低于join
。
注意#2:可能有更多方法可以实现,即通过使用:Zip, SkipWhile, TakeWhile等
注意 #3: 我做了上面的例子来展示 Linq 是多么有用、灵活和有趣;)
我有两个 KeyValuePair 类型的列表。
数值如下
List A
2019-01-01 1
2019-01-02 0
2019-01-03 1
List B
2019-01-01 0
2019-01-03 1
我想合并这两个列表,使其看起来像这样
List C
2019-01-01 0 //item from list B
2019-01-02 0 //item from list A, missing date in List B
2019-01-03 1 //item from list A - items are the same in list A and B
Linq 或 MoreLinq 有没有办法真正做到这一点,即。
- 合并两个列表中的项目
- 如果列表 B 中不存在相同的项目,则使用列表 A 中的项目
- 如果列表 A 中的项目不相等,则用列表 B 中的项目替换它们
我制定了这样的东西。请检查:
var q =
from a in ListA
join b in ListB on a.Dt equals b.Dt into j
from b in j.DefaultIfEmpty()
select new { Date=a.dt, Val = a.val == b?.val ? a.val : (b?.val ?? a.val) };
如果您知道您永远无法将默认 DateTime
作为密钥:
var r = from a in ListA
join b in ListB on a.Key equals b.Key into joined
from b in joined.DefaultIfEmpty()
select b.Key != default(DateTime) ? b : a;
如果您可能有一个默认的 DateTime
然后将键转换为 DateTime?
并再次返回以可靠地检测丢失的大小写:
var r = from a in ListA.Select(kv => new KeyValuePair<DateTime?, int>(kv.Key, kv.Value))
join b in ListB.Select(kv => new KeyValuePair<DateTime?, int>(kv.Key, kv.Value))
on a.Key equals b.Key into joined
from b in joined.DefaultIfEmpty()
select new KeyValuePair<DateTime, int>(b.Key ?? a.Key.GetValueOrDefault(), b.Value);
请注意,在两者中我们都跳过规则 "replace item from list A with item from list B if they are not equal",只使用 "use the item from B if it exists",因为我们必须检查 B 是否存在,如果 B 的值与 A 的值相同,则无关紧要我们仍然使用它。
我可能只是从 A 构建一个字典,然后用 B 的值替换值,除非我真的关心顺序。
请先阅读我对问题的评论。
var result = ListB
.Union(ListA)
.GroupBy(kvp=>kvp.Key)
.Select(grp=> new KeyValuePair<DateTime, int>(grp.Key, grp.Select(v=>v.Value).First()))
.OrderBy(kvp=>kvp.Key);
注意#1:我认为它的效率低于join
。
注意#2:可能有更多方法可以实现,即通过使用:Zip, SkipWhile, TakeWhile等
注意 #3: 我做了上面的例子来展示 Linq 是多么有用、灵活和有趣;)