Dynamically cross-join multiple different-size collections together in Linq (C#)

linq cross join
c# cross join two lists

I have an unknown number of buckets(collections), and each bucket having an unknown number of entities

I need to produce a cartesian product of all the entities, so that I endup with a single COLLECTION that has ARRAYS of entities and in each array, there is 1 representetive from EVERY bucket.

So that if I have 5 buckets (B1..B5), and buckets B1, B2 have 1 item each, and bucket B3, B4 and B5 have 4, 8 and 10 items each, I'll have a collection of 320 arrays, and each array will have 5 items.

The only stupud issue here, is that both size of buckets and number of buckets is unknown at development time.

Performance is not super important here, as most of the time, my buckets will have only 1 entity, and only rarely will there be times when some of my buckets will contain 20-30 items...and I'll usually have 5-30 buckets

I'd love to utilize linq here in someway, but my brain is getting fried as I try to imagine how this would work


You could create an extension method like the following:

public static class EnumerableExtensions
{
    public static IEnumerable<TValue []> Permutations<TKey, TValue>(this IEnumerable<TKey> keys, Func<TKey, IEnumerable<TValue>> selector)
    {
        var keyArray = keys.ToArray();
        if (keyArray.Length < 1)
            yield break;
        TValue [] values = new TValue[keyArray.Length];
        foreach (var array in Permutations(keyArray, 0, selector, values))
            yield return array;
    }

    static IEnumerable<TValue []> Permutations<TKey, TValue>(TKey [] keys, int index, Func<TKey, IEnumerable<TValue>> selector, TValue [] values)
    {
        Debug.Assert(keys.Length == values.Length);

        var key = keys[index];
        foreach (var value in selector(key))
        {
            values[index] = value;
            if (index < keys.Length - 1)
            {
                foreach (var array in Permutations(keys, index+1, selector, values))
                    yield return array;
            }
            else
            {
                yield return values.ToArray(); // Clone the array;
            }
        }
    }
}

As an example, it could be used like:

    public static void TestPermutations()
    {
        int [][] seqence = new int [][]
        {
            new int [] {1, 2, 3},
            new int [] {101},
            new int [] {201},
            new int [] {301, 302, 303},
        };

        foreach (var array in seqence.Permutations(a => a))
        {
            Debug.WriteLine(array.Aggregate(new StringBuilder(), (sb, i) => { if (sb.Length > 0) sb.Append(","); sb.Append(i); return sb; }));
        }
    }

and produce the following output:

1,101,201,301
1,101,201,302
1,101,201,303
2,101,201,301
2,101,201,302
2,101,201,303
3,101,201,301
3,101,201,302
3,101,201,303

Is that what you want?

Dynamically cross-join multiple different-size collections , 搜索. 写文章. 发布沸点. 登录. 2018年07月25日 阅读1. 关注. Dynamically cross- join multiple different-size collections together in Linq (C#) - Stack Overflow. 分享. When combining two data sources (or you can two collections) using Linq Cross Join, then each element in the first data source (i.e. first collection) will be mapped with each and every element in the second data source (i.e. second collection).


Here's how to do it without recursion in a single Linq statement (wrapped around an extension method for convenience):

public static IEnumerable<IEnumerable<T>> GetPermutations<T>(
                     IEnumerable<IEnumerable<T>> listOfLists)
{
    return listOfLists.Skip(1)
        .Aggregate(listOfLists.First()
                .Select(c => new List<T>() { c }),
            (previous, next) => previous
                .SelectMany(p => next.Select(d => new List<T>(p) { d })));
}

The idea is simple:

  1. Skip the first row, so we can use it as the initial value of an aggregate.
  2. Place this initial value in a list that we'll grow on each iteration.
  3. On each iteration, create a new list for each element in previous and add to it each of the elements in next (this is done by new List<T>(p) { d }).

EXAMPLE

Suppose you have an array of arrays as follows:

var arr = new[] {
  new[] { 1,2 },
  new[] { 10,11,12 },
  new[] { 100,101 }
};

Then arr.GetPermutations() will return a list of lists containing:

1,10,100
1,10,101
1,11,100
1,11,101
1,12,100
1,12,101
2,10,100
2,10,101
2,11,100
2,11,101
2,12,100
2,12,101

Performing Cross Joins with LINQ to Objects, Dynamically cross-join multiple different-size collections together in Linq (C#) - Stack Overflow � 阅读原文; 收藏. ivan132. IT @ CA. 1年前发布� 1人阅读. 暂无描述. In Visual Basic, LINQ provides two options for performing an INNER JOIN: an implicit join and an explicit join. An implicit join specifies the collections to be joined in a From clause and identifies the matching key fields in a Where clause. Visual Basic implicitly joins the two collections based on the specified key fields.


Non-Linq, non-recursive solution that's faster. We pre-allocate the entire output matrix and then just fill it in a column at a time.

T[][] Permutations<T>(T[][] vals)
{
    int numCols = vals.Length;
    int numRows = vals.Aggregate(1, (a, b) => a * b.Length);

    var results = Enumerable.Range(0, numRows)
                            .Select(c => new T[numCols])
                            .ToArray();

    int repeatFactor = 1;
    for (int c = 0; c < numCols; c++)
    {
        for (int r = 0; r < numRows; r++)
            results[r][c] = vals[c][r / repeatFactor % vals[c].Length];
        repeatFactor *= vals[c].Length;
    }

    return results;
}

Cross Join in LINQ, A cross join, also known as a Cartesian product, joins two sequences of values to that items in the first collection are used to produce multiple results, of items equal to the product of the sizes of the two source sequences. To create the data file. Copy the names.csv and scores.csv files into your project folder, as described in How to join content from dissimilar files (LINQ) (C#).. Example. The following example shows how to use a named type Student to store merged data from two in-memory collections of strings that simulate spreadsheet data in .csv format.


This is probably a very late answer, but I encounter a similar problem i.e. generate all permutations of a list of list of string. However, in my problem, I don't need all permutations simultaneously. I only need/generate next permutation if current permutation doesn't satisfy my condition. Therefore, the following is my way of doing a kind of "for each" and with conditional continuation during permutations generation. This answer is inpsired by Tom19's answer.

void ForEachPermutationDo<T>(IEnumerable<IEnumerable<T>> listOfList, Func<IEnumerable<T>, bool> whatToDo) {
    var numCols = listOfList.Count();
    var numRows = listOfList.Aggregate(1, (a, b) => a * b.Count());
    var continueGenerating = true;

    var permutation = new List<T>();
    for (var r = 0; r < numRows; r++) {
        var repeatFactor = 1;
        for (var c = 0; c < numCols; c++) {
            var aList = listOfList.ElementAt(c);
            permutation.Add(aList.ElementAt((r / repeatFactor) % aList.Count()));
            repeatFactor *= aList.Count();
        }

        continueGenerating = whatToDo(permutation.ToList()); // send duplicate
        if (!continueGenerating) break;

        permutation.Clear();
    }
}

Using the above method, generating all permutation can be done like

IEnumerable<IEnumerable<T>> GenerateAllPermutations<T>(IEnumerable<IEnumerable<T>> listOfList) {
    var results = new List<List<T>>();

    ForEachPermutationDo(listOfList, (permutation) => {
        results.Add(permutation);
        return true;
    });

    return results;
}

Learn How to Combine Data with a CROSS JOIN, Experienced Interviews � Internship Interviews � Competitive Programming � Design Patterns � Multiple Choice Quizzes Or in other words, we can say that cross join will produce a Cartesian product. Cross of the cross join. using System;. using System.Linq;. using System.Collections. emp_lang = "C++" , dpt_id = 3 },. Perform custom join operations. 12/01/2016; 5 minutes to read +3; In this article. This example shows how to perform join operations that aren't possible with the join clause. In a query expression, the join clause is limited to, and optimized for, equijoins, which are by far the most common type of join operation.


Another LINQ-based option, based on suggestion from Diego, but more precise in terms of argument and return types. It also does not require multiple enumerations of outer collection and hence does not produce Resharper's hint "Possible multiple enumerations".

public static IEnumerable<IReadOnlyCollection<T>> GetPermutations<T>(
    IEnumerable<IReadOnlyCollection<T>> collections) =>
        collections
            .Aggregate(
                new[] { Array.Empty<T>() },
                (acc, next) =>
                    acc
                        .SelectMany(accItem =>
                            next.Select(nextItem => accItem.Concat(new[] { nextItem }).ToArray()))
                        .ToArray());

The 10 Most Common Mistakes in C# Programming, Learn how to use a CROSS JOIN to return every combination of rows from two or more tables. A common use for a cross join is to create obtain all combinations of items, such as colors and sizes. Size FROM Color c CROSS JOIN Size s CROSS JOIN is just creating combinations from two separate distinct valued lists, � Join two DataTables using LINQ in C# August 12, 2015 by ashish shukla 1 Comment LINQ is a powerful language feature which allows us to query different data sources using the programming language syntax.We can use C# to query the data source whether it is Oracle,SQL Server or XML.The query we use will be same irrespective of the data source.


Comparison of C Sharp and Java, Languages that target the CLR benefit from features such as cross-language Programmers of C++, and many other languages, are accustomed to being in LINQ is great for abstracting the task of manipulating collections, whether they are called finalizers in C#) is that you can't know for sure when they will be called. Linq Join with Multiple Data Sources in C#. In this article, I am going to discuss how to perform Linq Join with Multiple data sources in C# with some examples. I strongly recommended you to read our previous article before proceeding to this article where we discussed how to perform Linq Join with two data sources in C# with some examples.


在Linq(C#)中将多个不同大小的集合动态交叉连接在一起| 码农网, Linq namespace that contains various extension methods for querying collections, such as Aggregate , All , Average , Distinct , Join , Union and many others. Cross Join or Cartesian product When combining two sequences using this process, every item in the first collection is combined with every item in the second one. No key selection is required as there is no filtering of data. The resultant sequence will always have a number of items equal to the product of the sizes of the two source sequences.


The first step in producing a left outer join of two collections is to perform an inner join by using a group join. (See Perform inner joins for an explanation of this process.) In this example, the list of Person objects is inner-joined to the list of Pet objects based on a Person object that matches Pet.Owner .