Mike
Mike

Reputation: 3284

How do i simplify 2 foreach using LINQ?

How can I do this in a more readable way?

 foreach (var actual in actualPositions)
 {
     foreach (var projection in projections)
     {
         var position        = Create(book, actual, projection);
         position.TargetNett = projection.DailyProjectedNet.ToString();
         yield return position;
     }
 }

Upvotes: 0

Views: 562

Answers (5)

Yuri Fedoseev
Yuri Fedoseev

Reputation: 569

In this case Linq provides less readability. You can move the second foreach statement in a seperate method and then use Linq

return from actual in actualPositions
       select GetBookPositionList(actual);

new method:

private List<BookPosition> GetBookPositionList(ActualPosition actual)
{
  foreach (var projection in projections)
  {
    var position = Create(book, actual, projection);
    position.TargetNett = projection.DailyProjectedNet.ToString();
    yield return position;
  }
}

Upvotes: 0

Serj-Tm
Serj-Tm

Reputation: 16981

just for fun

return 
 (
  from actual in actualProjections  
  from projection in projections  
  select new {actual, projection}
 ).Select(pair => 
   {
     var position = Create(book, pair.actual, pair.projection);   
     position.TargetNett = pair.projection.DailyProjectedNet.ToString();           
     return position;
   }
 );

Upvotes: 0

SPFiredrake
SPFiredrake

Reputation: 3892

One option you can do is to implement your own cross join, and enumerate over that. However, it's still not very pretty:

actualPositions.SelectMany(actual => projections.Select(project => new { actual, project }))

However, if you're using the .NET 4.0 or higher, you can implement a cross join extension method using Tuples (default) or your own custom selector:

public static IEnumerable<Tuple<T1, T2>> CrossJoin<T1, T2>(this IEnumerable<T1> source, IEnumerable<T2> toJoin)
{
    return source.CrossJoin(toJoin, Tuple.Create<T1, T2>);
}

public static IEnumerable<T3> CrossJoin<T1, T2, T3>(this IEnumerable<T1> source, IEnumerable<T2> toJoin, Func<T1, T2, T3> selector)
{
    return source.SelectMany(tFirst => toJoin.Select(tSecond => selector(tFirst, tSecond)));
}

And then this can be used a lot easier:

foreach(var pair in actualPositions.CrossJoin(projections))
{
    var position = Create(book, pair.Item1, pair.Item2);
    position.TargetNett = pair.Item2.DailyProjectedNet.ToString();
    yield return position;
}
// OR
return actionPositions.CrossJoin(projections, (actual, project) => { /*Code in foreach loop above here, without the "yield". */ });

Upvotes: 2

Serj-Tm
Serj-Tm

Reputation: 16981

return 
  from actual in actualProjections
  from projection in projections
  select Create(book, actual, projection)
          .With_TargetNett(projection.DailyProjectedNet.ToString());

where With_TargetNett is extension

static Position With_TargetNett(this Position position, string targetNett)
{
 position.TargetNett = targetNett;
 return position;
}

Upvotes: 2

jason
jason

Reputation: 241601

You want to simplify that? Why? It's simple and readable and understandable. You can come up with all sorts of gobbledygook that is harder to read but sure looks cooler. Do not! Resist the urge to be fancy.

Upvotes: 12

Related Questions