How to use Linq in 2 lists so that one complements the other in C#

Asked

Viewed 33 times

-1

Hello, I have the following situation:

public class Foo {
  int id { get; set; }
  Bar bar { get; set; }
}
public class Bar {
  int id { get; set; }
  int FooId { get; set; }
}
public class Program {
  public static void Main(string[] args){
    var foos = new List<Foo> {
      new Foo{ id: 1 }, new Foo{ id: 2 }, 
      new Foo{ id: 3 }, new Foo{ id: 4 }
    };
    var bars = new List<Bar> {
      new Bar{ id: 5, FooId: 2},
      new Bar{ id: 6, FooId: 4}
    }
  }
}

So I can insert the bars within their respective foos i have to use a foreach to check if the items have property FooId same as Foo id on the list, so:

foreach(var foo in foos)
  foreach(var bar in bars)
    if(bar.FooId == foo.Id)
      foo.Bar = bar;

If I were to do it in Linq, I would have to generate a new object and assign all the properties of the old one to the new one and then correlate, like this:

foos = foos
  .Join(bars,foo => foo.Id,bar => bar.FooId, (foo, bar) => new { foo, bar })
  .Select(x=> new Foo{ Id = x.foo.Id, Bar = x.bar })
  .ToList();

Is there any way I can harness the object of foos without the need to recreate it? The idea of this question is because I can do something similar in javascript like this:

var foos = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
var bars = [{id: 5, fooId: 2}, {id: 6, fooId: 4}];

foos = foos.map(x=> x.bar = bars.filter(y => y.fooId === x.id)[0])

1 answer

0


Your two examples (in c#) do not present the same results! The first (with chained foreach) the list gets the 4 elements and the second (with Join and select) the list gets only the 2 elements where the bar is not null

You can get the same result like this:

foreach (var foo in foos)
    foo.bar = bars.FirstOrDefault(b => b.FooId == foo.id);

It would actually be LastOrDefault..

Or so:

foos.ForEach(f => f.bar = bars.FirstOrDefault(b => b.FooId == f.id));

Or:

foos = foos.Select(f => { f.bar = bars.FirstOrDefault(b => b.FooId == f.id); return f; }).ToList();

To remove the nulls:

foos.RemoveAll(f => f.bar == null);
  • what I need is to return all items, regardless of whether they are null or not

  • 1

    @Leandroluk foos.ForEach(f => f.bar = bars.FirstOrDefault(b => b.FooId == f.id)); does not meet your need? I added another example, but is not as efficient if you seek efficiency your solution with foreach or with for will be the best.

  • I thought I would have some better way to use without foreach. After all Linq is very efficient in many situations...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.