Dynamically cross-join multiple different-size collections together in Linq (C#) -
i have unknown number of buckets(collections), , each bucket having unknown number of entities
i need produce cartesian product of entities, endup single collection has arrays of entities , in each array, there 1 representetive every bucket.
so if have 5 buckets (b1..b5), , buckets b1, b2 have 1 item each, , bucket b3, b4 , b5 have 4, 8 , 10 items each, i'll have collection of 320 arrays, , each array have 5 items.
the stupud issue here, both size of buckets , number of buckets unknown @ development time.
performance not super important here, of time, buckets have 1 entity, , there times when of buckets contain 20-30 items...and i'll have 5-30 buckets
i'd love utilize linq here in someway, brain getting fried try imagine how work
you create extension method 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 array; } } } }
as example, 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 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 want?
Comments
Post a Comment