Reputation: 43
I have three functions, one generates cartesian product with loops from 2 arrays, other one with loops from 3 arrays, and one with LINQ with 2 arrays. I want to write a LINQ solution to get it with 3 arrays.
private static string[][] CartesianProductSmart(string[] arr1, string[] arr2)
{
// for each s1 in arr1, extract arr2,
// then pass s1 and s2 into a newly-made string array.
return arr1.SelectMany(s1 => arr2, (s1, s2) => new string[] { s1, s2 })
.ToArray();
}
private static string[][] CartesianProductDumb(string[] arr1, string[] arr2)
{
// the dumb way; nested foreach
string[][] combos = new string[arr1.Length * arr2.Length][];
int ii = 0;
foreach (var strOne in arr1)
{
foreach (var strTwo in arr2)
{
string[] combo = new string[2];
combo[0] = strOne;
combo[1] = strTwo;
combos[ii] = combo;
ii++;
}
}
return combos;
}
private static string[][] CartesianProductDumbX3(string[] arr1, string[] arr2, string[] arr3)
{
// the dumb way; nested foreach
string[][] combos = new string[arr1.Length * arr2.Length * arr3.Length][];
int ii = 0;
foreach (var strOne in arr1)
{
foreach (var strTwo in arr2)
{
foreach (var strThree in arr3)
{
string[] combo = new string[3];
combo[0] = strOne;
combo[1] = strTwo;
combo[2] = strThree;
combos[ii] = combo;
ii++;
}
}
}
return combos;
}
The first two functions behave identically - they both return a cartesian product of 2 arrays. The third one does it with three arrays, how can I rewrite that function with LINQ? (Ultimately I want to write it so that I can give it any array number, but just 3 is good enough for now).
Upvotes: 0
Views: 388
Reputation: 37020
I'm not sure if this is what you're looking for, but it seems the simplest and most readable to me:
private static string[][] CartesianProductLinq(string[] arr1, string[] arr2,
string[] arr3)
{
return (from s1 in arr1
from s2 in arr2
from s3 in arr3
select new[] {s1, s2, s3}).ToArray();
}
If you prefer the method-chain syntax, it might look something like:
private static string[][] CartesianProductLinq(string[] arr1, string[] arr2,
string[] arr3)
{
return arr1
.SelectMany(s1 => arr2, (s1, s2) => new {s1, s2})
.SelectMany(result => arr3, (result, s3) => new[] {result.s1, result.s2, s3})
.ToArray();
}
Note the method names have been changed, since Linq is not inherently "smart", nor are loops inherently "dumb" (loops may be more efficient in some circumstances)
Upvotes: 2