Alexandre
Alexandre

Reputation: 13308

Convert to nested foreach into lambda expression

I want to convert nested foreach

foreach (Tuple<int, string, Guid> s in services)
     {
      foreach (BEPartnership p in partnership)
         {                                                                      
           p.Partner.Services = new List<Tuple<int, string>>(); 
             if (s.Item3 == p.Partner.Id)
               p.Partner.Services.Add(new Tuple<int, string>(s.Item1, s.Item2));
          }
    }

to something like this

services.SelectMany( 
 s=>partnership.Select(
 p=>new {partnerId = p.Partner.Id, servicePartnerId = s.Item3})
  .Where(x=>x.partnerId == x.servicePartnerId)
  .ToList()
  .ForEach( //....) )

Upvotes: 1

Views: 4543

Answers (3)

Josh G
Josh G

Reputation: 14256

First, I always create a static utility/extension class to define these methods:

public static void AddAll<T>(this ICollection<T> c, IEnumerable<T> items)
{
    items.ForEach(item => c.Add(item));
}

public static void AddAll<T1, T2>(this ICollection<T1> c, IEnumerable<T2> items, Func<T2, T1> converter)
{
    c.AddAll(items.Select(converter));
}

public static void ForEach<T>(this IEnumerable<T> e, Action<T> action)
{
    foreach (T item in e)
        action.Invoke(item);
}

Now all you need is this:

partnership.ForEach(p => 
    { 
        p.Partner.Services = new List<Tuple<int, string>>(); 
        p.Partner.Services.AddAll(from s in services
                 where s.Item3 == p.Partner.Id
                 select Tuple.Create(s.Item1, s.Item2))
    });

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174289

You are not really doing a query here, so LINQ might be the wrong approach.
However, you can change your two foreach loops to this:

foreach (var p in partnership)
    p.Partner.Services = new List<Tuple<int, string>>();

foreach (var s in services)
{
    partnership.Where(p => s.Item3 == p.Partner.Id).ToList().ForEach(
        p => p.Partner.Services.Add(new Tuple<int, string>(s.Item1, s.Item2)));
}

Does this really provides any benefit? I doubt it.

Going any further with SelectMany and stuff feels like raping LINQ, so I stopped here.

Upvotes: 1

Richard Ev
Richard Ev

Reputation: 54087

You could install the trial version of ReSharper 5, as this has a refactor option that will convert (if possible) a foreach loop into a LINQ expression.

http://blogs.jetbrains.com/dotnet/2009/12/resharper-50-preview-loops-2-linq/

Upvotes: 1

Related Questions