1

So, to keep it short, I have this bit of code in which I loop through the results of a string split and add them to a list, if they have not occurred before in the loop. This is the code.

var res = new List<string>();
foreach(string s in input.Split(new[] { ", " }, 
              StringSplitOptions.RemoveEmptyEntries))
{
    if(res.All(p => p != s))
        res.Add(s);
}

But after I wrote this code, Visual Studio said I could convert part of the loop into LINQ. However, I'm a bit skeptical about whether this'll work or not.

Basically, my question is, would the lambda expressions be executed on each separate loop, or just once in the beginning?

var res = new List<string>();
foreach (string s in input.Split(new[] { ", " }, 
              StringSplitOptions.RemoveEmptyEntries)
                          .Where(s => res.All(p => p != s)))
{
    res.Add(s);
}
Abishek
  • 11,191
  • 19
  • 72
  • 111
HugoC4
  • 51
  • 1
  • 6

3 Answers3

9

Here is the example of working lazy evaluation of Linq queries.

List<int> vals = new List<int> {1, 1, 2, 2, 3, 4};
var res = new List<int>();
foreach (int s in vals.Where(s => 
                       { 
                           Console.WriteLine("lambda"); 
                           return s % 2 == 0; 
                       }))
{
    Console.WriteLine("loop");
}

And the output will be

lambda
lambda
lambda
loop
lambda
loop
lambda
lambda
loop

As you can see lambda will be evaluated only when the next element is required by foreach loop

Dmitrii Dovgopolyi
  • 6,231
  • 2
  • 27
  • 44
  • 1
    This is a nice example and actually answers the question. – juharr Sep 28 '15 at 11:58
  • Actually, I find it doesn't explicitly answer the question *"Would the lambda expressions be executed on each separate loop, or just once in the beginning?"* because Dmitry says it will be evaluated *"only when the next element is required"* - this means that actually the lambda **is** evaluated *on each separate loop*. I would suggest changing the wording of the answer to reflect this fact better. – Marcus Mangelsdorf Oct 20 '15 at 07:15
7

Basically you are just trying to get the distinct values:

var res = input.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)
               .Distinct()
               .ToList();
Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
1

I built on Dmitry's answer and made output a little more verbose to show you what is really going on. Also note, that as Ufuk noted, there a better ways to achieve a list of distinct values.

Feel free to test this for your own and play around with it a little in this dotnetfiddle.

Here is the example:

List<int> input = new List<int> {1, 1, 2, 2, 3, 4};
var res = new List<int>();
foreach (int s in input.Where(s => 
    { 
        Console.WriteLine("lambda: s=" + s);
        Console.WriteLine("lambda: " + s + " contained in res? " + res.Contains(s));
        return !res.Contains(s);
    }))
{
    res.Add(s);
    Console.WriteLine("loop: " + s + " added to res");
    Console.WriteLine();
}

It produces the following output:

lambda: s=1
lambda: 1 contained in res? False
loop: 1 added to res

lambda: s=1
lambda: 1 contained in res? True
lambda: s=2
lambda: 2 contained in res? False
loop: 2 added to res

lambda: s=2
lambda: 2 contained in res? True
lambda: s=3
lambda: 3 contained in res? False
loop: 3 added to res

lambda: s=4
lambda: 4 contained in res? False
loop: 4 added to res
Marcus Mangelsdorf
  • 2,852
  • 1
  • 30
  • 40