【问题标题】:Querying for nullable relationship set of two lists [duplicate]查询两个列表的可空关系集[重复]
【发布时间】:2014-10-14 03:54:21
【问题描述】:

如果我有这些列表作为输入:

List<Record> A = new List<Record> { new Record { Value = 1 }, new Record { Value = 2 }, new Record { Value = 3 }, new Record { Value = 4 }, new Record { Value = 5 } };
List<Record> B = new List<Record> { new Record { Value = 1 }, new Record { Value = 2 }, new Record { Value = 5 }, new Record { Value = 7 } };

所以从上面看,A 有这些元素:

Record{Value = 1}
Record{Value = 2}
Record{Value = 3}
Record{Value = 4}
Record{Value = 5}

而 B 有这些元素:

Record{Value = 1}
Record{Value = 2}
Record{Value = 5}
Record{Value = 7}

我想要以下输出。 List&lt;Tuple&lt;Record, Record&gt;&gt;,在我们的例子中,列表如下所示:

Record{Value = 1} | Record{Value = 1}
Record{Value = 2} | Record{Value = 2}
Record{Value = 3} | null
Record{Value = 4} | null
Record{Value = 5} | Record{Value = 5}
null              | Record{Value = 7}

上面的第一列,代表我们元组中的第一个元素,只能包含来自A的对象,或者为null。上面的第二列,表示我们元组中的第二个元素,只能包含来自 B 的对象,或者为 null。记录不仅仅是一个值字段,因此不要将它们算作值类型,否则我会在我的问题中使用整数。

基本上,如您在示例中所见,A 中的对象进入输出数据类型的第一列,B 中的对象进入输出数据类型的第二列。如果 Value 字段中有匹配项,则它们并排显示。如果 A 和 B 之间的 value 字段没有匹配,则 null 转到相反的一侧,无论哪里没有匹配。

有没有办法通过 LINQ 查询数据集 A 和 B 来生成这样的结果数据类型?我对使用元组列表并不那么严格。我会用字典或其他类型的...

【问题讨论】:

  • google left join linq
  • 如果我理解正确的话,它更像是 t-sql 中的 full outer join。我过去编写了一个自定义 linq 运算符来执行此操作;这有点工作,但不是太多。一个问题:一侧的单个对象可以匹配另一侧的多个对象吗?您的示例没有显示这一点。
  • @Bart 这是完全外连接,而不是左连接。请注意示例结果中的最后一个元素。
  • @phoog 你说得对,先生。

标签: c# .net linq list linq-to-objects


【解决方案1】:

您可以首先通过将两个列表中的所有值连接在一起并获取不同的值来创建一个列表,然后您可以将该集合与两个集合中的每一个连接起来。

var values = A.Concat(B)
    .Select(record => record.Value)
    .Distinct();

var query = from value in values
    join a in A
    on value equals a.Value
    into aMatches
    join b in B
    on value equals b.Value
    into bMatches
    select Tuple.Create(aMatches.FirstOrDefault(), 
        bMatches.FirstOrDefault());

【讨论】:

  • +1 不错。我在评论中建议的自定义全外连接运算符将避免两次迭代这两个集合,但在大多数情况下,迭代两次对性能的影响可以忽略不计。因此,在这些情况下,成本/收益分析将支持这种方法。
  • @phoog 是的,他特别提到这些在内存集合中,因此将它们迭代两次根本不是问题。如果 IEnumerable 对象代表昂贵的延迟操作或导致副作用,这只是一个问题。
  • 或者如果内存中的集合很大,或者查询在(长时间运行的)循环中运行。
猜你喜欢
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2017-06-22
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 2020-05-31
相关资源
最近更新 更多