tags:

views:

158

answers:

4

Hi,

From what I understand about the where clause in LINQ, it combines elements from two or more sets based on all possible combinations of each element and then applies the criteria. For example:

public static void Main(string[] args)
{
    var setA = new[] {3, 4, 5};
    var setB = new[] {6, 7, 8};

    var result = from a in setA
                 from b in setB
                 let sum = a + b
                 where sum == 10            // Where, criteria sum == 10.
                 select new {a, b, sum};

    foreach (var element in result)
        Console.WriteLine("({0},{1}) == {2}", element.a, element.b, element.sum);

    Console.ReadLine();
}

This produces the following results before the where criteria is applied.

3,6 = 9    4,6 = 10    5,6 = 11
3,7 = 10   4,7 = 11    5,7 = 12
3,8 = 11   4,8 = 12    5,8 = 13

The results that match the criteria are 3,7 and 4,6. This produces the results:

(3,7) == 10
(4,6) == 10

However, from what I remember in grade school set theory, is there a way to provide the union of the two sets (pseudocode):

{3, 4, 5} union {6, 7, 8} = {3, 4, 5, 6, 7, 8}

Thanks,

Scott

+8  A: 
var Result = setA.Union(setB)

For a full listing of all the operators, look at Enumerable.

Chris
Oh. Ha ha, I sure feel dumb. When would I want to use where, generating all possible combinations ?
Scott Davies
+1  A: 

A Union is only one of 101 samples listed here:

http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx

Hamish Grubijan
+3  A: 

Where doesn't produce all possible pairings.... Where filters.

SelectMany produces all possible pairings:

var pairings = SetA
    .SelectMany(a => SetB, (a, b) => new {a, b} );

or

var pairings =
  from a in SetA
  from b in SetB
  select new {a, b};

Due to deferred execution, linq to object query claues are evaluated in a different order than you might suspect. Recall: queries are not evaluated until they are enumerated (such as - used in a foreach loop or a .ToList() method call). Consider the original query with a couple extra method calls:

var result = (
    from a in setA 
    from b in setB 
    let sum = a + b 
    where sum == 10
    select new {a, b, sum}
).Take(2).ToList(); 

The actual order of evaluation proceeds in this fashion

* ToList calls its inner enumerable
  * Take(2) calls its inner enumerable
    * Select calls its inner enumerable
      * Where calls its inner enumerable
        * from (setb) calls its inner enumerable
          * from (seta) returns 3 from seta
        * from (setb) returns a pairing of 3 and 6
      * Where filters out the pairing and calls its inner enumerable for another one
        * from (setb) returns a pairing of 3 and 7
      * Where checks the pairing and returns it
    * Select uses the pairing to create the anonymous instance.
  *Take(2) returns the anonymous instance and remembers that it has returned once.
*ToList adds the element to a List
*ToList calls its inner enumerable
  * Take(2) calls its inner enumerable
    * Select calls its inner enumerable
      * Where calls its inner enumerable
        * from (setb) returns a pairing of 3 and 8
      * Where filters out the pairing and calls its inner enumerable for another one
        * from (setb) calls its inner enumerable
          * from (seta) returns 4 from seta
        * from (setb) returns a pairing of 4 and 6
      * Where checks the pairing and returns it
    * Select uses the pairing to create the anonymous instance.
  *Take(2) returns the anonymous instance and remembers that it has returned twice.
*ToList adds the instance to a List.
*ToList askes Take(2) if there's any more, and Take(2) say no.
*ToList returns the list.
David B
It does filter, but before it filters it creates the pairings, doesn't it ?
Scott Davies
the pairings are created - before 'where' filters them. 'where' has nothing to do with pairing creation. let's be specific and not use the word "it".
David B
Ah, sorry. Ok, so the order of events would be: 1. Pairings, 2. Filter based on where ?
Scott Davies
Sure, the "declared" order of events is construct pairings, then filter. The actual order of events gets mixed up by deferred execution. See edit for example.
David B
+1  A: 
new []{1,2,3}.Concat(new [] {4,5,6});
George Polevoy
That's creative; I hadn't considered that.
Scott Davies