score:6
the best way to understand this code is to read the amazing serial post from eric lippert:
- producing combinations, part one
- producing combinations, part two
- producing combinations, part three
- producing combinations, part four
- producing combinations, part five
basically, if we have a ienumerable
of 5 items, and want to get all combinations size of 3, we need to produce something like this:
{
// 50, 60, 70, 80, 90
{50, 60, 70}, // t t t f f
{50, 60, 80}, // t t f t f
{50, 60, 90}, // t t f f t
{50, 70, 80}, // t f t t f
{50, 70, 90}, // t f t f t
{50, 80, 90}, // t f f t t
{60, 70, 80}, // f t t t f
{60, 70, 90}, // f t t f t
{60, 80, 90}, // f t f t t
{70, 80, 90} // f f t t t
}
eric's recursive implementation:
// takes integers n and k, both non-negative.
// produces all sets of exactly k elements consisting only of
// integers from 0 through n - 1.
private static ienumerable<tinyset> combinations(int n, int k)
{
// base case: if k is zero then there can be only one set
// regardless of the value of n: the empty set is the only set
// with zero elements.
if (k == 0)
{
yield return tinyset.empty;
yield break;
}
// base case: if n < k then there can be no set of exactly
// k elements containing values from 0 to n - 1, because sets
// do not contain repeated elements.
if (n < k)
yield break;
// a set containing k elements where each is an integer from
// 0 to n - 2 is also a set of k elements where each is an
// integer from 0 to n - 1, so yield all of those.
foreach(var r in combinations(n-1, k))
yield return r;
// if we add n - 1 to all the sets of k - 1 elements where each
// is an integer from 0 to n - 2, then we get a set of k elements
// where each is an integer from 0 to n - 1.
foreach(var r in combinations(n-1, k-1))
yield return r.add(n-1);
}
in your case, the code is working like this:
return k == 0
// if we are done, return empty array
? new[] {new t[0]}
// for each element and each number from 0 to enumerable size
: elements.selectmany((e, i) =>
elements
//skip first i elements, as we already produced combination with them
.skip(i + 1)
//get all the combinations with size k - 1
.combinations(k - 1)
//add current element to all produced combinations
.select(c => (new[] {e}).concat(c)));
this code in non-recursive form will be very huge and unreadable, try to understand the recursion:
say, we have a 5 elements ienumerable
: { 16, 13, 2, 4, 100 }
, and we need to all the combinations from it with size of 2 (total numbers of resulting sets is equal to binomial coefficient from 5 to 2 = 5! / (2! * 3!) = 10
)
your code will be producing:
- for the
16
we need all the combinations of size1
, starting from second position: - for the element
13
we need all the combinations of size0
starting from the third position - first result:
{ 16, 13 }
- skip the
13
, for the element2
we need all the combinations of size0
starting from the fourth position - second result:
{ 16, 2 }
- skip the
13, 2
, for the element4
we need all the combinations of size0
starting from the fifth position - third result:
{ 16, 4 }
- skip the
13, 2, 4
, for the element100
we need all the combinations of size0
starting from the sixth position - fourth result:
{ 16, 100 }
- ... repeat all the above from
13
,2
,4
:
{ 13, 2 }
,{ 13, 4 }
,{ 13, 100 }
,{ 2, 4 }
,{ 2, 100 }
,{ 4, 100 }
and we got all the 10 combinations we need. the overload the code author is using is this: enumerable.selectmany<tsource, tresult> method (ienumerable<tsource>, func<tsource, int32, ienumerable<tresult>>)
:
selector
type:system.func<tsource, int32, ienumerable<tresult>>
a transform function to apply to each source element;
the second parameter of the function represents the index of the source element.
score:0
my none linq version, should be correct!
test results:
linq style:
123
124
125
134
135
145
234
235
245
345
my way:
123
124
125
134
135
145
234
235
245
345
my code
/// <summary>
/// get the full combinations of k elements from a given list.
/// </summary>
public static list<list<t>> mycombinations<t>(this list<t> elements, int k)
{
int n = elements.count;
//given the same sequence, what if we wish to choose none of them? there does exist a subsequence which has zero elements, so we should produce it; the answer would be { { } }
if (k == 0)
{
return new list<list<t>> {new list<t> {}};
}
if (k == n)
{
return new list<list<t>> {elements};
}
// what if we have a sequence of five items and we wish to choose six of them? there is no way to do that; there is no six-element subsequence. so the answer should be { }, the empty sequence of sequences
if (k > n)
{
return new list<list<t>> {};
}
var result = new list<list<t>> {};
for (int i = 0; i < n; i++)
{
t cur = elements[i];
var rest = elements.skip(i + 1).tolist();//take out current elment to fetch combinations of the rest set
var combinationsofrest = mycombinations<t>(rest, k - 1);
var currentlist = new list<t> {cur};
foreach (list<t> combination in combinationsofrest)
{
result.add(currentlist.concat(combination).tolist());
//combination.add(cur);
//result.add(combination);
}
}
return result;
}
Source: stackoverflow.com
Related Query
- How to understand the following C# linq code of implementing the algorithm to return all combinations of k elements from n
- How can I write the following code more elegantly using LINQ query syntax?
- How to convert the following code to LINQ format?
- How to convert the following foreach loop to linq code format?
- How does the following LINQ statement work?
- How does linq actually execute the code to retrieve data from the data source?
- How to code the partial extensions that Linq to SQL autogenerates?
- How to do the following in Dynamic Linq using System.Linq.Dynamic namespace
- How to avoid loop by using LINQ for the following code?
- How do I do the following Linq / Lambda code?
- How does the CLR interpret the following LINQ query
- How can we express the following code using query expression?
- How to swap the data source associated with a Linq query?
- How to write this code using the Linq Extension Method-Syntax?
- How can I check the number of calls to the database in LINQ query when using .NET Core and Code First?
- How do I determine the source of unpredictable LINQ query results?
- How to do the following in LINQ
- How do I do the following using Lambda or Linq statement?
- How to simplify the code Using LINQ
- How do i create the following LINQ expression dynamically?
- How can I write the "Where" clause in the following LINQ to SQL Query?
- How can i change the following LINQ query as normal sql query
- How much less efficent would the linq technique be in the following case and could either be optimised?
- How to write aggregate query in LINQ reusing part of the select code
- How to execute code as a part of the LINQ query
- What SQL query or LINQ code would get the following data?
- How do I write a LINQ query which will generate a JSON string with the following format?
- How can I condense the following Linq query into one IQueryable
- How to write the following in LINQ syntax?
- Shortcut LINQ toentity query for the following code in MVC 3
More Query from same tag
- Linq to Sql - Convert C# to VB.NET help
- How to use partition by in Linq query in C#, to add column values in subsequent rows?
- How cast System.Data.Entity.Infrastructure.DbQuery type to System.Collections.Generic.List type?
- LINQ's Left outer join column selection
- LINQ to Xml not equal to operator
- Recursive linq to get infinite children
- Instantiate empty IQueryable for use with Linq to sql
- How can I dynamically combine a set of LINQ queries at runtime?
- Checking for case sensitivity within .Any in NHibernate
- How can I write this query in linq?
- Using Menu Buttons to modify LINQ search terms
- Linq Objects Group By & Sum
- How to perform this EF Core nested date comparison query in SQL
- Binding data from database to a label control in asp.net
- linq query to create new objects
- LINQ distinct entries
- How to dynamically group a list and select values using linq query in C#?
- How can I create a sub-list from a list in c#?
- Linq most efficient way
- Grouping files by common text in names using Lambda
- Order by Descending with multiple comparisons
- How would you write this map-filter chain using LINQ?
- Check if a table exists within a database using LINQ
- Sort List of Parent / Child Objects
- Entity Framework Generic Predicate
- dynamically create lambdas expressions + linq + OrderByDescending
- Linq error in the select statement
- An unhandled exception of type 'System.ArgumentNullException' occurred in System.Xml.Linq.dll Additional information: Value cannot be null
- Reference to an ITVF raises a "second operation started on this context before a previous operation completed" exception
- Compare list elements with string