如何在LINQ中获取查询的“余数”(所有非匹配对)并将其收集到列表中

时间:2014-03-13 09:49:18

标签: c# linq

我将请求与基于requestId的响应进行匹配,如下所示:

    public void MatchCallPairsByRequestId()
    {
        // Finds request that have matching response based on RequestId and create callpair
       _callPairs = _requests.Where(req => !string.IsNullOrEmpty(req.RequestId))
                  .Join(_responses, 
                        req => req.RequestId,
                        resp => resp.RequestId,
                        (req, resp) => new CallPair(req, resp)).ToList();
    }

或在LINQ表达式中:

 _callPairs = (from req in _requests
                  join resp in _responses
                      on req.RequestId equals resp.RequestId
                      where !string.IsNullOrEmpty(req.RequestId)
                  select new CallPair(req, resp)).ToList();

现在,我想在名为nonMatchedRequestsnonMatchedResponses的单独列表中收集与该功能不匹配的请求和响应。如何使用此查询在单独的列表中收集余数?

3 个答案:

答案 0 :(得分:3)

我不确定是否有办法在一次调用中执行此操作,或者甚至将其与生成对列表合并,但您可以运行几个后续方法来确定不匹配的项:

var unmatchedRequests = _requests.Except(_callPairs.Select(cp => cp.Request));

var unmatchedResponses = _responses.Except(_callPairs.Select(cp => cp.Response));

Enumerable.Join的文档也谈到能够使用GroupJoin执行外部联接,如详细here,这将返回无法匹配的请求,但我认为它会错过无与伦比的响应。

我屏住呼吸地等待着答案,证明了linq巫术可以通过一次通话更有效地完成这项任务。

答案 1 :(得分:2)

查找返回的CallPair对象中不存在的请求和响应

var unmatchedRequests = _requests.Where(req => !_callPairs.Any(cp => cp.Request == req));
var unmatchedResponses = _responses.Where(resp => !_callPairs.Any(cp => cp.Response == resp));

编辑:这是一些示例代码

var requests = Enumerable.Range(0, 10).Select(i => "Request" + i).ToList();
var responses = Enumerable.Range(0, 10).Select(i => "Response" + i).ToList();

var pairs = Enumerable.Range(0, 3).Select(i => new KeyValuePair<string, string>("Request" + i, "Response" + i * 2)).ToList();

var unmatchedRequests = requests.Where(req => !pairs.Any(cp => cp.Key == req));
var unmatchedResponses = responses.Where(resp => !pairs.Any(cp => cp.Value == resp));

我得到7个不匹配的请求和7个不匹配的响应,看起来是正确的。您的某些请求是否与多个响应匹配,反之亦然?

答案 2 :(得分:2)

您可以通过.Except()执行此操作,也可以使用不同的值

// Matching pairs
_callPairs = _requests.Where(req => !string.IsNullOrEmpty(req.RequestId))
    .Join(
        _responses, 
        req => req.RequestId,
        resp => resp.RequestId, 
        (req, resp) => new CallPair(req, resp)
    ).ToList();

// To use the .Distinct() part, you're going to need to implement IEqualityComparer twice
// Easy but maybe not strictly necessary, no matter what it would be a solid approach
var matchedRequests = _callPairs.Select(cp => cp.Request); //.Distinct(new RequestComparer());
var matchedResponses = _callPairs.Select(cp => cp.Response); //.Distinct(new ResponseComparer());

var nonMatchingRequests = _requests.Except(matchedRequests);
var nonMatchingResponses = _responses.Except(matchedResponses);