Hooked on LINQ

Hooked on LINQ - Developers' Wiki
for .NET Language Integrated Query

Quick Search

Advanced Search »

Join Operator

Modified: 2007/01/16 23:41 by t_magennis - Categorized as: LINQ to Objects
{TOC}
Namespace:System.Linq
Assembly:System.Core.dll
Extends:IEnumerable<T>

Back to Standard Query Operator Index


Edit

Introduction

The Join operator performs an inner join of two sequences based on matching keys extracted from the elements.

(if you need outer join behaviour, where outer elements with no matching inner elements are also returned, see Outer Join Sample.

Edit

Method Signatures

// 1 - Join with another source
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
    this IEnumerable<TOuter> outer, 
    IEnumerable<TInner> inner, 
    Func<TOuter, TKey> outerKeySelector, 
    Func<TInner, TKey> innerKeySelector, 
    Func<TOuter, TInner, TResult> resultSelector)
 
// New in January CTP
// 2 - Join with another source, use custom comparer function for equality testing of keys.
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
    this IEnumerable<TOuter> outer, 
    IEnumerable<TInner> inner, 
    Func<TOuter, TKey> outerKeySelector, 
    Func<TInner, TKey> innerKeySelector, 
    Func<TOuter, TInner, TResult> resultSelector, 
    IEqualityComparer<TKey> comparer)



Edit

Exceptions

Throws an ArgumentNullException if outer, inner, outerKeySelector, innerKeySelector or resultSelector are null.

Edit

Pseudo-code

Overload 1
If outer is null, throw an ArgumentNullException.
If inner is null, throw an ArgumentNullException.
If outerKeySelector is null, throw an ArgumentNullException.
If innerKeySelector is null, throw an ArgumentNullException.
If resultSelector is null, throw an ArgumentNullException.
(Create a lookup table of groups based on the inner sequence key's evaluated by the innerKeySelector call it "inner groupings".)
Iterate the inner sequence.
Determine the key of this element as the result innerKeySelector(current element).
If this key is already grouped.
Add the current element to that group.
else, create a group for this key value.
Add the current element to the new group group.
(Match inner and outer groups and return results)
Iterate the outer sequence.
Find the grouping in "inner groupings" that matches the result of outerKeySelector(current element) call it "element group" using the EqualityComparer<TSource>.Default comparer function.
Iterate the "element group".
Return resultSelector(current element in "element group"). (Resume execution from here when the next element is requested).

Overload 2
If outer is null, throw an ArgumentNullException.
If inner is null, throw an ArgumentNullException.
If outerKeySelector is null, throw an ArgumentNullException.
If innerKeySelector is null, throw an ArgumentNullException.
If resultSelector is null, throw an ArgumentNullException.
If comparer is null, default to EqualityComparer<TSource>.Default;
(Create a lookup table of groups based on the inner sequence key's evaluated by the innerKeySelector call it "inner groupings".)
Iterate the inner sequence.
Determine the key of this element as the result innerKeySelector(current element).
If this key is already grouped.
Add the current element to that group.
else, create a group for this key value.
Add the current element to the new group group.
(Match inner and outer groups and return results)
Iterate the outer sequence.
Find the grouping in "inner groupings" that matches the result of outerKeySelector(current element) call it "element group" using the comparer function.
Iterate the "element group".
Return resultSelector(current element in "element group"). (Resume execution from here when the next element is requested).

Note: By this pseudo-code you can see that if there are no matching inner elements for a given outer element key, then no elements are yielded for that outer element. If you want to yield a result for non-matched outer elements, see Outer Join Sample.

Edit

Loop count

1 full loop of the inner sequence. Looping over the outer sequence happens as the result is iterated. This operator implements the standard deferred execution iterator pattern. This means, no looping will occur until the result is iterated over.

Edit

Code Samples

public static void JoinSimpleExample()
{
    var customers = new List<Customer>() { 
        new Customer {Key = 1, Name = "Gottshall" },
        new Customer {Key = 2, Name = "Valdes" },
        new Customer {Key = 3, Name = "Gauwain" },
        new Customer {Key = 4, Name = "Deane" },
        new Customer {Key = 5, Name = "Zeeman" } 
    };
 
    var orders = new List<Order>() {
        new Order {Key = 1, OrderNumber = "Order 1" },
        new Order {Key = 1, OrderNumber = "Order 2" },
        new Order {Key = 4, OrderNumber = "Order 3" },
        new Order {Key = 4, OrderNumber = "Order 4" },
        new Order {Key = 5, OrderNumber = "Order 5" },
    };
 
    var q = from c in customers
            join o in orders on c.Key equals o.Key
            select new {c.Name, o.OrderNumber};
 
    foreach (var i in q) {
        Console.WriteLine("Customer: {0}  Order Number: {1}", 
            i.Name.PadRight(11, ' '), i.OrderNumber);
    }
 
    Console.ReadLine();
}
 
public class Customer
{
    public int Key;
    public string Name;
}
 
public class Order
{
    public int Key;
    public string OrderNumber;
}



Customer: Gottshall    Order Number: Order 1
Customer: Gottshall    Order Number: Order 2
Customer: Deane        Order Number: Order 3
Customer: Deane        Order Number: Order 4
Customer: Zeeman       Order Number: Order 5

If you would like to comment on this page, click on the Discuss button located on the top-right of each page. Feel free to edit any mistakes or ommissions you find. If you have an objection or find in-appropriate content then contact the administrator. This website is not affiliated with Microsoft®, all content and opinions are those of the specific author and some advice, solutions and article may contain un-intentional errors - please use care. Powered by ScrewTurn Wiki version 2.0.33. Some of the icons created by FamFamFam.