0

There is a long and tedious way I could perform the task I want to accomplish, but I am thinking there must be a way using Linq or some other neater more efficient technique to achieve this. I have a IEnumberable lets call it people1 with properties firstName and lastName, I also have a List lets call it people2 also with firstName and lastName properties. I need to store only the people1 where the firstName and lastName values of people2 match that of people1.

This pseudo code doesn't work but it might explain better what I hope to achieve than that wordy explanation:

people3 = people1.Select(x => x.firstName IN (people2.firstName) && x.lastName IN (people2.lastName))

I am kinda new to this so the only way I came up with of doing it was looping through the people2 list elements comparing people1 and if it matches storing it in people3. This will work but I am assuming there is a nicer way to do it and I am trying to learn new things so I thought I would throw this out there to see what your great minds come up with. :)

UPDATE:

After playing around a bit I am close but can't seem to figure out how to add the matching items to a new IEnumerable object. Here is the code I have, it fails on the "Add" line:

IEnumerable<dynamic> people3 = null;

foreach(var person in people1)
{
   if(people2.Exists(x => x.FirstName == people1.FirstName))
   {
      people3.Add(person);
   }
}
mgrenier
  • 1,409
  • 3
  • 21
  • 45
  • 1
    you can use join for multiple fields: http://stackoverflow.com/questions/373541/how-to-do-joins-in-linq-on-multiple-fields-in-single-join – Ric Dec 02 '14 at 18:48
  • Per your update you are going about this the wrong way. First, `people3` is never even initialized a non-null value, so calling any member on it would never work. Second, `IEnumerable` doesn't have an `Add()` method. Third, the correct solution will involve composing your existing `IEnumerable` instances to form a new one; you won't have to create one explicitly, because it will simply be returned by whatever composition mechanism you're using. – Peter Duniho Dec 02 '14 at 19:21
  • I understand there is no Add for IEnumberable I was just attempting to show what I was trying to do. I guess I should have said that. My problem is I can find when there is a match between people1 and people2 but I can't put the results anywhere. An acceptable results for me, which seems to be what you are implying is the correct method, would be removing non-matches. I am ok with this, can you offer some sample code I am not sure how to remove elements. – mgrenier Dec 02 '14 at 19:28

2 Answers2

4

NOTICE: This solution is only applicable for sequences of the same type.

Enumerable.Intersect<T>(IEnumerable<T>, IEnumerable<T>, IEqualityComparer<T>)


Basically, you want to use linq to find the matches between two sequences using a custom equality comparison, which in your case would compare true for the FirstName and LastName matching. Though, what would happen if two people shared the same exact name but they are different people? If that isn't an issue in your domain, then ignore that problem.

Ivan Kochurkin
  • 4,413
  • 8
  • 45
  • 80
myermian
  • 31,823
  • 24
  • 123
  • 215
  • This isn't bad, but the question seems to imply that the two enumerations are of different element types. A LINQ `join` may be more appropriate, depending on the actual scenario. – Peter Duniho Dec 02 '14 at 18:56
  • 3
    @PeterDuniho: I don't see where the question implies the two sequences are of different types, what in particular indicates that? – myermian Dec 02 '14 at 18:58
  • because s/he describes the lists according to the properties the elements have, rather than by the types themselves. If the two lists were actually the same type, it's likely (but of course not certain) that would have actually been mentioned. Instead, the lists are being described according to _characteristics_ of the members, implying that while the members of each list are similar in this way, there are also differences between them (i.e. different element types). – Peter Duniho Dec 02 '14 at 19:05
  • @PeterDuniho: I think it's safer to assume the latter, that the types are matching types unless otherwise stated. It is less likely that they are of different types with matching properties. Though, if the OP wants to clarify that in the question, then I will adjust my answer to indicate that this would require matching types so it would not be a viable solution. – myermian Dec 02 '14 at 19:10
  • It's "safer" to assume the scenario that has _more_ prerequisites? Um...okay. – Peter Duniho Dec 02 '14 at 19:18
  • the lists are different types that is correct. One is an IEnumerable and the other is a List as mentioned in the original question. I can't compare them directly, I can only compare the string values of firstname and lastname that I matching on. – mgrenier Dec 02 '14 at 19:22
  • @m-y thanks for the suggestion, I am not attempting for the first and last names to be a unique identifier here only to return a list which matches my criteria. The user can potentially enter only a firstname and will return several results (depending on the name). There is not worries about return multiple results here. – mgrenier Dec 02 '14 at 19:23
  • @mgrenier: In that case, I have updated my answer to indicate that this is not a solution for your problem space, you will need an alternative solution. – myermian Dec 02 '14 at 19:30
0

I am aware this probably isn't the most elegant solution, however this is the best way I was able to figure out how to accomplish my goal. Please if you have improvement by all mean I am open to making this piece of code a little nicer.

//populate IEnumerable<dynamic> people1
//populate List<dynamic> people2

List<dynamic> people3 = new List<dynamic>();

foreach (var person in people1)
   if(people2.Exists(x=>x.FirstName==person.FirstName)
      people3.Add(person);

people1 = people3;

I was hoping to avoid a for loop but I think the fact that I have 2 different sequence types has made it inevitable.

mgrenier
  • 1,409
  • 3
  • 21
  • 45