user2609980
user2609980

Reputation: 10474

Using LINQ to create pairs from two different list where the entries have same attribute

I have two lists of Requests and Responses who inherit from the abstract AbstractLineModel class. Both the responses and requests contain an ID (or not) named RequestId.

A CallPair contains a matching pair of Request and a Response and has the following constructor:

public AbstractLineModel _request { get; set; }
public AbstractLineModel _response { get; set; }

public CallPair(AbstractLineModel request, AbstractLineModel response)
{
    _request = request;
    _response = response;
}

I want to make a List of CallPairs where the Request with the same Id as the Response are matched in the Callpair. How to match the list of Requests and Responses?

What I tried is:

public void MatchCallPairs()
{
    // Finds request that have matching response
    var requestWithMatches = _requests
        .Where(req => _responses.All(res => res.RequestId == req.RequestId)).ToList();

    // Match the request to the response
    foreach (var req in requestWithMatches)
    {
        var resp = _responses.Where(res => res.RequestId == req.RequestId).FirstOrDefault();

        // And create the pairs
        _callPairs.Add(new CallPair(req, resp));
    }
}

but this returns an empty list.

Specifically, var requestWithMatches = _requests .Where(req => _responses.All(res => res.RequestId == req.RequestId)).ToList(); returns an empty list of requestsWithMatches.

Can someone help me out with this algorithm?

Upvotes: 4

Views: 965

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

Just join both sequences on RequestId and create CallPair from joined items:

 var requestWithMatches = from req in _requests
                          join resp in _responses
                             on req.RequestId equals resp.RequestId
                          select new CallPair(req, resp);

Upvotes: 4

Tim Schmelter
Tim Schmelter

Reputation: 460048

You can use Enumerable.Join for this:

public void MatchCallPairs()
{
    // Finds request that have matching response
    var requestWithMatches = from req in _requests
                             join resp in _responses
                             on req.RequestId equals resp.RequestId
                             select new CallPair(req, resp);
    _callPairs =  requestWithMatches.ToList();
}

Apart from the fact that this is more efficient, your code was incorrect:

_responses.All(res => res.RequestId == req.RequestId)

since that checks if All responses' RequestId are the same.

Upvotes: 2

Related Questions