如何使用linq或moreLinq

时间:2019-02-08 11:44:16

标签: c# linq 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中的项目

3 个答案:

答案 0 :(得分: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)  };

答案 1 :(得分: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,则将密钥转换为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);

请注意,在这两个规则中,我们都跳过了“将列表A中的项目替换为列表B中的项目,如果它们不相等”的规则,而忽略了“使用B中的项目(如果存在)”的规则,因为我们必须检查B是否仍然存在,如果B的值与A的值相同,那么我们仍然使用它也没关系。

除非我真的很在乎顺序,否则我可能只是从A构建字典,然后将其替换为B的值。

答案 2 :(得分: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是多么有用,灵活和有趣;)