Onetx
Onetx

Reputation: 88

Select two comparers in two list with same property value

I want to compare two List<Candidate> and select both entities with same value in the Hash property.

public class  Candidate : IEquatable<Candidate>
{
    public string Name { get; set; }
    public String Hash { get; set; }
}

//....

//List with "CandidateA", "CandidateB", "CandidateC" values
List<Candidate> newsCandidate = loadNewsCandidate();

//List with "CandidateC' " , "CandidateD", "CandidateE" values
List<Candidate> previousCandidate = loadPreviousCandidate();

//CandidateC and CandidateC' has same 'Hash' value.

//This return "CandidateC" in newsCandidate
var common = newsCandidate.Where(n => previousCandidate.Any(p => p.Hash.Equals(n.Hash))).ToList();

I want retrieve a List<Tuple<Candidate,Candidate>> or similar, with elements n.CandidateC and p.CandidateC' and output a message similar to:

 $"Previous Name: {p.CandidateC.Name} to New Name: {n.CandidateC.Name}"

Will apreciate any help.

Upvotes: 1

Views: 52

Answers (2)

Johnny
Johnny

Reputation: 9509

It seems GroupBy could be useful:

var p = new List<Candidate> 
{ 
    new Candidate { Name = "John", Hash = "1" }, 
    new Candidate { Name = "Mike", Hash = "2" } 
};

var n = new List<Candidate> 
{ 
    new Candidate { Name = "Mike", Hash = "1" }, 
    new Candidate { Name = "John", Hash = "2" } 
};

var joined = p.Concat(n).GroupBy(item => item.Hash);

Console.WriteLine(string.Join("\n", joined
    .Where(g => g.Count() == 2)
    .Select(g => $"Old name {g.First().Name}, New name {g.Last().Name}")));

// Old name John, new name Mike
// Old name Mike, new name John

or just make List<Tuple<Candidate, Candidate>> with:

List<Tuple<Candidate, Candidate>> tuple = joined
    .Where(g => g.Count() == 2)
    .Select(g => new Tuple<Candidate, Candidate>(g.First(), g.Last()))
    .ToList();

Upvotes: 0

NetMage
NetMage

Reputation: 26907

Perhaps the simplest thing to do would be to create a Dictionary from the previous candidates and lookup each match:

var prevDict = previousCandidate.ToDictionary(pc => pc.Hash);
var ans = newsCandidate.Select(nc => prevDict.TryGetValue(nc.Hash, out var pc) ? new { pc, nc } : null).Where(pcnc => pcnc != null);

If you prefer not to manually build your own Dictionary, you can also use the LINQ Join to do the same thing:

var ansj = previousCandidate.Join(newsCandidate, pc => pc.Hash, nc => nc.Hash, (pc, nc) => new { pc, nc });

Upvotes: 1

Related Questions