Combinations of Multiple Lists

I’m not quite sure that the term “Combination” is correct, but I have a requirement to create a list of combinations from one or more lists. Each list will contain a different number of items, for example.

List<string> lBag1 = ["1_0, 1_1, 1_3"] List<string> lBag2 = ["11_0, 11_1, 11_8"] List<string> lBag3 = ["3_0"] 

I need the whole combination of form lists from 1 to n elements containing no more than one element from each list, for example

 "1_0" "1_1" "1_3" "11_0" "11_1" "11_8" "3_0" "1_0 11_0" "1_0 11_1" "1_0 11_8" "1_0 3_0" ... "1_3 11_8 3_0" 

The order is not important, so "1_0 11_0" is considered the same as "11_0 1_0".

Any help would be greatly appreciated.

0
c # combinations
source share
3 answers

These two extension methods allow you to combine several enumerations, calculating the combinations you want.

Each combination is an enumeration, not a concatenated string.

 // This method takes two sequences of T, and returns // - each element of the first sequence, // wrapped in its own one-element sequence // - each element of the second sequence, // wrapped in its own one-element sequence // - each pair of elements (one from each sequence), // as a two-element sequence. // eg { 1 }.CrossWith({ 2 }) returns { { 1 }, { 2 }, { 1, 2 } } public static IEnumerable<IEnumerable<T>> CrossWith<T>( this IEnumerable<T> source1, IEnumerable<T> source2) { foreach(T s1 in source1) yield return new[] { s1 }; foreach(T s2 in source2) yield return new[] { s2 }; foreach(T s1 in source1) foreach(T s2 in source2) yield return new[] { s1, s2 }; } // This method takes a sequence of sequences of T and a sequence of T, // and returns // - each sequence from the first sequence // - each element of the second sequence, // wrapped in its own one-element sequence // - each pair, with the element from the second sequence appended to the // sequence from the first sequence. // eg { { 1, 2 } }.CrossWith({ 3 }) returns // { { 1, 2 }, { 3 }, { 1, 2, 3 } } public static IEnumerable<IEnumerable<T>> CrossWith<T>( this IEnumerable<IEnumerable<T>> source1, IEnumerable<T> source2) { foreach(IEnumerable<T> s1 in source1) yield return s1; foreach(T s2 in source2) yield return new[] { s2 }; foreach(IEnumerable<T> s1 in source1) foreach(T s2 in source2) yield return s1.Concat(new[] { s2 }).ToArray(); } var cross = lBag1.CrossWith(lBag2).CrossWith(lBag3); // { "1_0" }, { "1_1" }, { "1_3" } ... // ... { "1_0", "11_0" }, ... 

Also, there is this classic Eric Lippert post that does a similar thing. (A similar result, a very different method.)

+1
source share

This works for you:

 var empty = new string[] { null, }; var query = from b1 in empty.Concat(lBag1) from b2 in empty.Concat(lBag2) from b3 in empty.Concat(lBag3) let bs = new [] { b1, b2, b3 }.Where(b => b != null) let result = String.Join(" ", bs) where result != "" select result; 
+1
source share

This is just my opinion. You must decide how to implement it yourself, but I would:

1) Create a class to represent your X_Y pairs

2) Make your class Implement IEquatable

3) Provide implementations for Equal

4) Implement a constructor that, given a string in the form of X_Y, returns a YourClass object.

5) Implement a public static function that, if a string containing a list of sections with an X_Y comma, returns a list

6) Use the previous method to create three lists.

7) Create an empty list

8) Use yourList.Append to add items from trhee lists.

Perhaps I use weapons to kill flies.

0
source share

All Articles