Method FullGroupJoin
| Edit this pageFullGroupJoin<TFirst, TSecond, TKey>(IEnumerable<TFirst>, IEnumerable<TSecond>, Func<TFirst, TKey>, Func<TSecond, TKey>)
Performs a Full Group Join between the first and second sequences.
Declaration
public static IEnumerable<(TKey Key, IEnumerable<TFirst> First, IEnumerable<TSecond> Second)> FullGroupJoin<TFirst, TSecond, TKey>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TKey> firstKeySelector, Func<TSecond, TKey> secondKeySelector)
Parameters
| Type | Name | Description |
|---|---|---|
| IEnumerable<TFirst> | first | First sequence |
| IEnumerable<TSecond> | second | Second sequence |
| Func<TFirst, TKey> | firstKeySelector | The mapping from first sequence to key |
| Func<TSecond, TKey> | secondKeySelector | The mapping from second sequence to key |
Returns
| Type | Description |
|---|---|
| IEnumerable<(TKey Key, IEnumerable<TFirst> First, IEnumerable<TSecond> Second)> | A sequence of elements joined from |
Type Parameters
| Name | Description |
|---|---|
| TFirst | The type of the elements in the first input sequence |
| TSecond | The type of the elements in the second input sequence |
| TKey | The type of the key to use to join |
Remarks
This operator uses deferred execution and streams the results. The results are yielded in the order of the elements found in the first sequence followed by those found only in the second. In addition, the callback responsible for projecting the results is supplied with sequences which preserve their source order.
Examples
The following code example demonstrates how to execute a full group join using FullGroupJoin
var people = new Person[]
{
new("John Doe", 1),
new("Jane Doe", 1),
new("Lucy Ricardo", 2),
new("Ricky Ricardo", 2),
new("Fred Mertz", 3),
new("Ethel Mertz", 3),
};
var pets = new Pet[]
{
new("Bear", 3),
new("Polly", 2),
new("Minnie", 2),
new("Mittens", 1),
new("Patches", 1),
new("Paws", 1),
};
var results = people
.FullGroupJoin(
pets,
p => p.FamilyId,
p => p.FamilyId);
foreach (var (familyId, familyPeople, familyPets) in results)
{
var str1 = string.Join(", ", familyPeople.Select(p => p.Name));
var str2 = string.Join(", ", familyPets.Select(p => p.Name));
Console.WriteLine($"({familyId}, [{str1}], [{str2}])");
}
// This code produces the following output:
// (1, [John Doe, Jane Doe], [Mittens, Patches, Paws])
// (2, [Lucy Ricardo, Ricky Ricardo], [Polly, Minnie])
// (3, [Fred Mertz, Ethel Mertz], [Bear])
record Person(string Name, int FamilyId);
record Pet(string Name, int FamilyId);
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException |
|
FullGroupJoin<TFirst, TSecond, TKey>(IEnumerable<TFirst>, IEnumerable<TSecond>, Func<TFirst, TKey>, Func<TSecond, TKey>, IEqualityComparer<TKey>?)
Performs a Full Group Join between the first and second sequences.
Declaration
public static IEnumerable<(TKey Key, IEnumerable<TFirst> First, IEnumerable<TSecond> Second)> FullGroupJoin<TFirst, TSecond, TKey>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TKey> firstKeySelector, Func<TSecond, TKey> secondKeySelector, IEqualityComparer<TKey>? comparer)
Parameters
| Type | Name | Description |
|---|---|---|
| IEnumerable<TFirst> | first | First sequence |
| IEnumerable<TSecond> | second | Second sequence |
| Func<TFirst, TKey> | firstKeySelector | The mapping from first sequence to key |
| Func<TSecond, TKey> | secondKeySelector | The mapping from second sequence to key |
| IEqualityComparer<TKey> | comparer | The equality comparer to use to determine whether or not keys are equal. If null, the
default equality comparer for |
Returns
| Type | Description |
|---|---|
| IEnumerable<(TKey Key, IEnumerable<TFirst> First, IEnumerable<TSecond> Second)> | A sequence of elements joined from |
Type Parameters
| Name | Description |
|---|---|
| TFirst | The type of the elements in the first input sequence |
| TSecond | The type of the elements in the second input sequence |
| TKey | The type of the key to use to join |
Remarks
This operator uses deferred execution and streams the results. The results are yielded in the order of the elements found in the first sequence followed by those found only in the second. In addition, the callback responsible for projecting the results is supplied with sequences which preserve their source order.
Examples
The following code example demonstrates how to execute a full group join using FullGroupJoin
var people = new Person[]
{
new("John Doe", 1),
new("Jane Doe", 1),
new("Lucy Ricardo", 2),
new("Ricky Ricardo", 2),
new("Fred Mertz", 3),
new("Ethel Mertz", 3),
};
var pets = new Pet[]
{
new("Bear", 103),
new("Polly", 102),
new("Minnie", 102),
new("Mittens", 101),
new("Patches", 101),
new("Paws", 101),
};
var results = people
.FullGroupJoin(
pets,
p => p.FamilyId,
p => p.FamilyId,
new IntBy100Comparer());
foreach (var (familyId, familyPeople, familyPets) in results)
{
var str1 = string.Join(", ", familyPeople.Select(p => p.Name));
var str2 = string.Join(", ", familyPets.Select(p => p.Name));
Console.WriteLine($"({familyId}, [{str1}], [{str2}])");
}
// This code produces the following output:
// (1, [John Doe, Jane Doe], [Mittens, Patches, Paws])
// (2, [Lucy Ricardo, Ricky Ricardo], [Polly, Minnie])
// (3, [Fred Mertz, Ethel Mertz], [Bear])
record Person(string Name, int FamilyId);
record Pet(string Name, int FamilyId);
class IntBy100Comparer : IEqualityComparer<int>
{
public bool Equals(int x, int y) =>
x % 100 == y % 100;
public int GetHashCode(int obj) =>
(obj % 100).GetHashCode();
}
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException |
|
FullGroupJoin<TFirst, TSecond, TKey, TResult>(IEnumerable<TFirst>, IEnumerable<TSecond>, Func<TFirst, TKey>, Func<TSecond, TKey>, Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult>)
Performs a full group-join between two sequences.
Declaration
public static IEnumerable<TResult> FullGroupJoin<TFirst, TSecond, TKey, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TKey> firstKeySelector, Func<TSecond, TKey> secondKeySelector, Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult> resultSelector)
Parameters
| Type | Name | Description |
|---|---|---|
| IEnumerable<TFirst> | first | First sequence |
| IEnumerable<TSecond> | second | Second sequence |
| Func<TFirst, TKey> | firstKeySelector | The mapping from first sequence to key |
| Func<TSecond, TKey> | secondKeySelector | The mapping from second sequence to key |
| Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult> | resultSelector | Function to apply to each pair of elements plus the key |
Returns
| Type | Description |
|---|---|
| IEnumerable<TResult> | A sequence of elements joined from |
Type Parameters
| Name | Description |
|---|---|
| TFirst | The type of the elements in the first input sequence |
| TSecond | The type of the elements in the second input sequence |
| TKey | The type of the key to use to join |
| TResult | The type of the elements of the resulting sequence |
Remarks
This operator uses deferred execution and streams the results. The results are yielded in the order of the elements found in the first sequence followed by those found only in the second. In addition, the callback responsible for projecting the results is supplied with sequences which preserve their source order.
Examples
The following code example demonstrates how to execute a full group join using FullGroupJoin
var people = new Person[]
{
new("John Doe", 1),
new("Jane Doe", 1),
new("Lucy Ricardo", 2),
new("Ricky Ricardo", 2),
new("Fred Mertz", 3),
new("Ethel Mertz", 3),
};
var pets = new Pet[]
{
new("Bear", 3),
new("Polly", 2),
new("Minnie", 2),
new("Mittens", 1),
new("Patches", 1),
new("Paws", 1),
};
var results = people
.FullGroupJoin(
pets,
p => p.FamilyId,
p => p.FamilyId,
(familyId, familyPeople, familyPets) =>
{
var str1 = string.Join(", ", familyPeople.Select(p => p.Name));
var str2 = string.Join(", ", familyPets.Select(p => p.Name));
return $"({familyId}, [{str1}], [{str2}])";
});
foreach (var str in results)
Console.WriteLine(str);
// This code produces the following output:
// (1, [John Doe, Jane Doe], [Mittens, Patches, Paws])
// (2, [Lucy Ricardo, Ricky Ricardo], [Polly, Minnie])
// (3, [Fred Mertz, Ethel Mertz], [Bear])
record Person(string Name, int FamilyId);
record Pet(string Name, int FamilyId);
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException |
|
FullGroupJoin<TFirst, TSecond, TKey, TResult>(IEnumerable<TFirst>, IEnumerable<TSecond>, Func<TFirst, TKey>, Func<TSecond, TKey>, Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult>, IEqualityComparer<TKey>?)
Performs a full group-join between two sequences.
Declaration
public static IEnumerable<TResult> FullGroupJoin<TFirst, TSecond, TKey, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TKey> firstKeySelector, Func<TSecond, TKey> secondKeySelector, Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
Parameters
| Type | Name | Description |
|---|---|---|
| IEnumerable<TFirst> | first | First sequence |
| IEnumerable<TSecond> | second | Second sequence |
| Func<TFirst, TKey> | firstKeySelector | The mapping from first sequence to key |
| Func<TSecond, TKey> | secondKeySelector | The mapping from second sequence to key |
| Func<TKey, IEnumerable<TFirst>, IEnumerable<TSecond>, TResult> | resultSelector | Function to apply to each pair of elements plus the key |
| IEqualityComparer<TKey> | comparer | The equality comparer to use to determine whether or not keys are equal. If null, the
default equality comparer for |
Returns
| Type | Description |
|---|---|
| IEnumerable<TResult> | A sequence of elements joined from |
Type Parameters
| Name | Description |
|---|---|
| TFirst | The type of the elements in the first input sequence |
| TSecond | The type of the elements in the second input sequence |
| TKey | The type of the key to use to join |
| TResult | The type of the elements of the resulting sequence |
Remarks
This operator uses deferred execution and streams the results. The results are yielded in the order of the elements found in the first sequence followed by those found only in the second. In addition, the callback responsible for projecting the results is supplied with sequences which preserve their source order.
Examples
The following code example demonstrates how to execute a full group join using FullGroupJoin
var people = new Person[]
{
new("John Doe", 1),
new("Jane Doe", 1),
new("Lucy Ricardo", 2),
new("Ricky Ricardo", 2),
new("Fred Mertz", 3),
new("Ethel Mertz", 3),
};
var pets = new Pet[]
{
new("Bear", 103),
new("Polly", 102),
new("Minnie", 102),
new("Mittens", 101),
new("Patches", 101),
new("Paws", 101),
};
var results = people
.FullGroupJoin(
pets,
p => p.FamilyId,
p => p.FamilyId,
(familyId, familyPeople, familyPets) =>
{
var str1 = string.Join(", ", familyPeople.Select(p => p.Name));
var str2 = string.Join(", ", familyPets.Select(p => p.Name));
return $"({familyId}, [{str1}], [{str2}])";
},
new IntBy100Comparer());
foreach (var str in results)
Console.WriteLine(str);
// This code produces the following output:
// (1, [John Doe, Jane Doe], [Mittens, Patches, Paws])
// (2, [Lucy Ricardo, Ricky Ricardo], [Polly, Minnie])
// (3, [Fred Mertz, Ethel Mertz], [Bear])
record Person(string Name, int FamilyId);
record Pet(string Name, int FamilyId);
class IntBy100Comparer : IEqualityComparer<int>
{
public bool Equals(int x, int y) =>
x % 100 == y % 100;
public int GetHashCode(int obj) =>
(obj % 100).GetHashCode();
}
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException |
|