1

我有两个 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 中的项目
4

3 回答 3

2

我制定了这样的东西。请检查:

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)  };
于 2019-02-08T11:53:16.180 回答
2

如果您知道您永远不能将默认值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,则将键转换为 aDateTime?并再次返回以可靠地检测丢失的大小写:

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);

请注意,在两者中,我们都跳过了规则“如果它们不相等,则将列表 A 中的项目替换为列表 B 中的项目”,而只使用“如果存在则使用 B 中的项目”,因为我们必须检查 B 是否存在,以及 B 是否存在值与 A 相同,那么我们仍然使用它并不重要。

不过,除非我真的关心顺序,否则我可能只是从 A 构建一个字典,然后用 B 中的值替换这些值。

于 2019-02-08T12:05:31.793 回答
0

请先阅读我对问题的评论。

另一种方法是将UnionGroupBy结合使用

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:可能有更多方法可以实现这一点,即通过使用:ZipSkipWhileTakeWhile等。

注意#3:我做了上面的例子来展示 Linq 是多么有用、灵活和有趣;)

于 2019-02-08T12:42:25.977 回答