0

I have 2 lists of 2 different objects:

public class A {
    string Id;
    string Name;
    List<B> listofB;
}

public class B {
    string Id;
    string Test;
}

The Id in B is the same as the Id in A

now I have 2 lists

var listA = new List<A>();
var listB = new List<B>();

How would you add every B object where the Id's match to the list of A via linq?

for now I did:

foreach(var a in listA){
   a.listofB = listB.FindAll(i => i.Id == a.Id);
}

But I would think there is a better way of doing this

(This always returns null for now, still trying to figure out why)

Kiwi
  • 2,713
  • 7
  • 44
  • 82
  • 1
    Can you add more sample code in order to test for us? Also, what is `findAll`? – Patrick Hofman May 11 '15 at 08:03
  • findAll is a linq function – Kiwi May 11 '15 at 08:04
  • 1
    _"But I would think there is a better way of doing this"_ If that's working for you, why do you think that there's something better? It's readable and probably efficient. – Tim Schmelter May 11 '15 at 08:05
  • 2
    He probably means [`List.FindAll`](https://msdn.microsoft.com/en-us/library/fh1w7y8z(v=vs.110).aspx) (which is not part of LINQ btw) – dcastro May 11 '15 at 08:05
  • 1
    FindAll should return an empty list (if no elements found): https://msdn.microsoft.com/en-us/library/fh1w7y8z%28v=vs.110%29.aspx not null. I think you should provide more code in order for us to help and I think it's more likely a lazy loading problem. – Fourat May 11 '15 at 08:07
  • @TimSchmelter: I would think there are queries for better inner linking objects, instead of a simple foreach. – Kiwi May 11 '15 at 08:10
  • @dcastro indeed that is the one, srry I was thinking it was part of linq – Kiwi May 11 '15 at 08:10
  • @Kiwi You're not necessarily linking objects though, you're assigning a property of each item in a `List`, which requires iteration. – Mathew Thompson May 11 '15 at 08:11
  • What you have is good enough. I would remove the items from listB after adding them to list A though. Like this: listB.RemoveAll(x => x.Id == a.Id); – danish May 11 '15 at 08:22

3 Answers3

4

But I would think there is a better way of doing this

If that's working for you, why do you think that there's something better? It's readable and probably efficient.

However, you could use Enumerable.Join + GroupBy:

var idGrps = from a in listA
             join b in listB
             on a.Id equals b.Id into bGroup
             select new { a, bGroup };
foreach (var grp in idGrps)
{
    grp.a.listofB = grp.bGroup.ToList();
}

But even if Join is more efficient if the lists are large, it's not as readable. Maybe it's better to initialize the list from the A-constructor from the start instead of maintaining two lists.

Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

Use GroupJoin

void Main()
{
    var alist = new List<A>();
    var blist = new List<B>();

    result = alist.GroupJoin(
        blist,
        a=>a.Id,    //Pick group key from A
        b=>b.Id,    //Pick group key from B
        (singleA,manyB)=>
            new{TheA=singleA,AllTheBs=manyB.ToList()}); //Create a resulting object.
}
Tormod
  • 4,551
  • 2
  • 28
  • 50
0

You could use a GroupBy clause:

var theBsById = listB.GroupBy(b => b.Id);

and then:

foreach(IGrouping<int, B> grouping in theBsById)
{
    A theA = listA.Where(a => a.Id == grouping.Key).FirstOrDefault();
    if (theA != null)
    {
        theA.listofB = grouping.ToList();
    }
}

(This would only update the listofBs in the As that have Ids in listB)

or:

foreach(var a in listA)
{
    a.listofB = theBsById
      .Where(grouping => grouping.Key == a.Id)
      .SelectMany(grouping => grouping)
      .ToList();
}

(this would update the listofB for all As, which is what your code above does, too.)

J S
  • 901
  • 8
  • 15
  • If this is really more readable and more efficient than the approach the OP currently uses is another question... – MakePeaceGreatAgain May 11 '15 at 08:15
  • You replaced a solution with 2 nested iterations with a solution that uses 2 nested iterations and a GroupBy Iteration and lost readability in the process. – Ralf May 11 '15 at 08:16