Reputation: 2195
I've got two lists of different objects.
List<ObjA> objAs = new List<ObjA>();
List<ObjB> objBs = new List<ObjB>();
They have the following class structures.
public class ObjA
{
public int Id;
public int ObjBId;
}
public class ObjB
{
public int Id;
public string Title;
}
Joining objA's ObjBId
property to ObjB's Id
property, I want to create a list of ObjA's Ids alongside ObjB's Titles. Something like this:
List<int, string> output = new List<int, string>();
// where int = ObjA's Id, string = ObjB's Title
How can I do this in LINQ? Are there any alternative than using Concat and creating a wrapper class?
Upvotes: 2
Views: 6769
Reputation: 358
You can use a join and return a list
var result = (from a in objAs
join b in objBs on a.ObjBId equals b.Id
select new
{
a.ObjBId,
b.Title
}).ToList();
Upvotes: 2
Reputation: 23228
You can use Join
method and return a result as list of named tuples List<(int, string)>
(available beginning with C# 7), becuase List<int, string>
isn't a valid C# declaration.
var output = objAs.Join(objBs, a => a.ObjBId, b => b.Id, (a, b) => (a.Id, b.Title)).ToList();
You may also use anonymous objects instead of tuples, e.g. (a, b) => new { a.Id, b.Title}
Upvotes: 4
Reputation: 30464
So for every element of objAs, you want to take the Id, and if an object with the same Id is in objBs, you want the Id from objA and the title from objB.
In fact, since the Id of objA and objB are equal, you don't care if you take the Id from objA or from objB.
You didn't write what you want if there is no item in objBs with the same Id. Let's assume you want null in that case.
var result = objAs.GroupJoin(objBs, // GroupJoin A with B
objA => objA.Id, // from every element in A take the Id
objB => objB.Id, // from every element in B take the Id
// ResultSelector: take all elements of A, each with the matching elements from B
(objA, matchingObjBs) => new
{
Id = objA.Id,
Title = matchingObjBs.Select(objB => objB.Title).FirstOrDefault(),
});
The nice thing about GroupJoin, is that you also get the element from A that have no matching B. And if there are more than one matching item in B, you take the first one.
If you don't want the items from A that have no matching Id in B, it is enough to take only the elements from B that have an Id in A:
var idsA = objAs.Select(objA => objA.Id);
var result = objBs.Where(objB => idsA.Contains(objB.Id));
Upvotes: 0
Reputation: 18155
Enumerable.Join
should help you in this.
var result = objAs.Join(objBs,x=>x.ObjBId,y=>y.Id,(x,y)=>new {x.Id,y.Title})
.ToList();
Upvotes: 2