Get distinct Combinations of numbers using LINQ - c#
The below code returns all distinct combinations based on the logic that 1,2,3 = 3,2,1 = 2,3,1, so it only returns 1 instance of that set of numbers.
However, I want to change that logic so that it returns ALL instances of all number sets.
What do I need to do to the LINQ query below "GetPowerSet" in order to make that happen?
public void GetPowersets()
{
List<int> ints = new List<int>()
{
1,2,2,3,3
};
var results = GetPowerSet(ints);
List<String> combinations = new List<String>();
foreach (var result in results)
{
StringBuilder sb = new StringBuilder();
foreach (var intValue in result.OrderBy(x => x))
{
sb.Append(intValue + ",");
}
combinations.Add(sb.ToString());
}
string c1 = string.Join("|", combinations.ToArray()).Replace(",|", "|");
//c1 = "|1|2|1,2|2|1,2|2,2|1,2,2|3|1,3|2,3|1,2,3|2,3|1,2,3|2,2,3|1,2,2,3|3|1,3|2,3|1,2,3|2,3|1,2,3|2,2,3|1,2,2,3|3,3|1,3,3|2,3,3|1,2,3,3|2,3,3|1,2,3,3|2,2,3,3|1,2,2,3,3,"
}
public IEnumerable<IEnumerable<int>> GetPowerSet(List<int> list)
{
return from m in Enumerable.Range(0, 1 << list.Count)
select
from i in Enumerable.Range(0, list.Count)
where (m & (1 << i)) != 0
select list[i];
}
This is the end result I am trying to achieve: (no duplicate rows of combinations: duplicate = 3,2,1 and 3,2,1 are the same thing. but 1,2,3 and 3,2,1 are NOT the same thing and both should be in the end result)
1
2
3
1,2
1,3
2,1
2,3
2,2
3,1
3,2
3,3
1,2,3
1,2,2
1,3,2
1,3,3
2,1,3
2,1,2
2,3,1
2,3,2
2,3,3
2,2,1
2,2,3
3,1,2
3,1,3
3,2,1
3,2,2
3,2,3
3,3,1
3,3,2
1,2,3,2
1,2,3,3
1,2,2,3
1,3,2,2
1,3,2,3
1,3,3,2
2,1,3,2
2,1,3,3
2,1,2,3
2,3,1,2
2,3,1,3
2,3,2,1
2,3,2,3
2,3,3,1
2,3,3,2
2,2,1,3
2,2,3,1
2,2,3,3
3,1,2,2
3,1,2,3
3,1,3,2
3,2,1,2
3,2,1,3
3,2,2,1
3,2,2,3
3,2,3,1
3,2,3,2
3,3,1,2
3,3,2,1
3,3,2,2
1,2,3,2,3
1,2,3,3,2
1,2,2,3,3
1,3,2,2,3
1,3,2,3,2
1,3,3,2,2
2,1,3,2,3
2,1,3,3,2
2,1,2,3,3
2,3,1,2,3
2,3,1,3,2
2,3,2,1,3
2,3,2,3,1
2,3,3,1,2
2,3,3,2,1
2,2,1,3,3
2,2,3,1,3
2,2,3,3,1
3,1,2,2,3
3,1,2,3,2
3,1,3,2,2
3,2,1,2,3
3,2,1,3,2
3,2,2,1,3
3,2,2,3,1
3,2,3,1,2
3,2,3,2,1
3,3,1,2,2
3,3,2,1,2
3,3,2,2,1
The "foreach" way of doing this, which tends to cause a "Out Of Memory Exception" once the number set gets too large (I anticipate LINQ shouldn't have this problem) is below. This works as I want it to, returning the result set I want. But it is slow and has performance issues. I'm also open to suggestions on how to make it better.
public List<List<int>> GetAllCombinationsOfAllSizes(List<int> ints)
{
List<List<int>> returnResult = new List<List<int>>();
var distinctInts = ints.Distinct().ToList();
for (int j = 0; j < distinctInts.Count(); j++)
{
var number = distinctInts[j];
var newList = new List<int>();
newList.Add(number);
returnResult.Add(newList);
var listMinusOneObject = ints.Select(x => x).ToList();
listMinusOneObject.Remove(listMinusOneObject.Where(x => x == number).First());
if (listMinusOneObject.Count() > 0)
{
_GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref returnResult);
}
}
return returnResult;
}
public void _GetAllCombinationsOfAllSizes(List<int> ints, List<int> growingList, ref List<List<int>> returnResult)
{
var distinctInts = ints.Distinct().ToList();
for (int j = 0; j < distinctInts.Count(); j++)
{
var number = distinctInts[j];
var newList = growingList.ToList();
newList.Add(number);
returnResult.Add(newList);
var listMinusOneObject = ints.Select(x => x).ToList();
listMinusOneObject.Remove(listMinusOneObject.Where(x => x == number).First());
if (listMinusOneObject.Count() > 0)
{
_GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref returnResult);
}
}
}
The ANSWER I am looking for is: how to achieve this result set I want , but using LINQ and C# to do it, in a way that is faster and more efficient than the current "foreach" way I have posted?
NEW UPDATE (removed old code, performance is better than OP's code, yielded output)
static IEnumerable<int[]> EnumeratePermutations2(int[] ints)
{
Dictionary<int, int> intCounts = ints.GroupBy(n => n)
.ToDictionary(g => g.Key, g => g.Count());
int[] distincts = intCounts.Keys.ToArray();
foreach (int[] permutation in EnumeratePermutations2(new int[0], intCounts, distincts))
yield return permutation;
}
static IEnumerable<int[]> EnumeratePermutations2(int[] prefix, Dictionary<int, int> intCounts, int[] distincts)
{
foreach (int n in distincts)
{
int[] newPrefix = new int[prefix.Length + 1];
Array.Copy(prefix, newPrefix, prefix.Length);
newPrefix[prefix.Length] = n;
yield return newPrefix;
intCounts[n]--;
int[] newDistincts = intCounts[n] > 0
? distincts
: distincts.Where(x => x != n).ToArray();
foreach (int[] permutation in EnumeratePermutations2(newPrefix, intCounts, newDistincts))
yield return permutation;
intCounts[n]++;
}
}
I didn't touch your GetPowerSet, but instead created a SetComparer to filter the repetitions.
public class SetComparer : IEqualityComparer<IEnumerable<int>>
{
public bool Equals(IEnumerable<int> x, IEnumerable<int> y)
{
return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y));
}
public int GetHashCode(IEnumerable<int> set)
{
if (set == null) return 0;
//if you only want one of these 1,2,3 vs 3,2,1
//plug .OrderBy(x => x) before the Aggregate
return set.Aggregate(19, (s,i) => s * 31 + i);
}
}
Just chain .Distinct(new SetComparer()) to the results or at the end of your GetPowerSet select statement.
Based on the question.
Your solution does return all result sets including duplicates. Your solutions does not exclude duplicates. Your Example output does exclude some duplicates but you list 89 sets of data.
There should only be 64 with duplicates as I understand how combinations work which is 2 ^ List.Count() = 2 ^ 6 = 64 combinations
Revised Answer
I believe this is close to what you want. I created a short solution but I think it can be re factored and enhanced for speed. The following Link has some good Set Classes which I think should be used: http://www.codeproject.com/Articles/23391/Set-Collections-for-C
The other thing I would use is the TPL Library which will allow you to speed up the processing. Link: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
My Result Set resulted in 190 sets. With the following code it took about 1.5 minutes to run.
Main Program
void Main()
{
var setList = new List<int>() {1,1,2,3,3,3};
var setSize = setList.Count();
var basePowerSet = PowerSet.Generate(setList);
var results = PowerSet.PS;
// Results generated in 1 Minute 23 seconds with no errors.
var sortedSets = new SortedSet<string>();
foreach( var item in results)
{
sortedSets.Add(item.ToString2());
}
foreach( var item in sortedSets)
{
Console.WriteLine(item);
}
}
PowerSet Library
public static class PowerSet
{
// List with no Exact Duplicates but with Permutations
public static List<List<int>> PS = new List<List<int>>();
// This Method Generates the power set with No Exact Duplicates
// and stores the values into the Property PS.
public static List<List<int>> Generate(List<int> setList)
{
// Generate Base Data to use for final results
var setSize = setList.Count();
var basePowerSet = from m in Enumerable.Range(0, 1 << setSize)
select
from i in Enumerable.Range(0, setSize)
where (m & (1 << i)) != 0
select setList[i];
// Temporary Result Set with Duplicates
var results = new List<List<int>>();
// Step thru each set and generate list of Permutations for each
// Power Set generated above.
foreach( var item in basePowerSet )
{
var size = item.Count();
var positions = from m in Enumerable.Range(0, size)
select m;
var lItem = item.ToList();
// If the set has 2 or more elements in the set then generate Permutations
switch(size)
{
case 0:
case 1:
break;
default:
// Permutations generated from Linq Extension defined
// in Method Permute()
var posList = positions.Permute().ToList();
// remove first item which is a duplicate.
posList.RemoveAt(0);
// Generate new Lists based on all possiable
// combinations of the data in the set.
var x = new List<List<int>>();
foreach(var p in posList)
{
var y = new List<int>();
foreach(var v in p)
{
//v.Dump("xxxx");
y.Add(lItem[v]);
}
x.Add(y);
// Add New Permutation but
// Do not add a duplicate set.
AddNonDuplicate(x);
}
break;
}
// Add to Temp Results;
results.Add(item.ToList());
// Remove Duplicates
AddNonDuplicate(results);
}
return results;
}
// Custom Method used to compare values in a set to the
// Final Result Set named PS.
public static void AddNonDuplicate(List<List<int>> list )
{
//list.Dump();
if(list.Count() == 0)
return;
foreach(var item in list)
{
bool found = false;
var mySize = PS.Count();
if(mySize <= 0)
PS.Add(item);
else
foreach(var psItem in PS)
{
if( item.ToString2() == psItem.ToString2() )
found = true;
}
if(!found)
PS.Add(item);
}
}
}
Extension Library
// My Extension Methods
public static class MyExt
{
public static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> list)
{
if (list.Count() == 1)
return new List<IEnumerable<T>> { list };
return list
.Select((a, i1) =>
Permute(list.Where((b, i2) => i2 != i1))
.Select(b => (new List<T> { a }).Union(b)))
.SelectMany(c => c);
}
public static string ToString2<T>(this List<T> list)
{
StringBuilder results = new StringBuilder("{ ");
var size = list.Count();
var pos = 1;
foreach( var i in list )
{
results.Append(i.ToString());
if(pos++!=size)
results.Append(", ");
}
results.Append(" }");
return results.ToString().Trim(',');
}
}
Results
{ }
{ 1 }
{ 1, 1 }
{ 1, 1, 2 }
{ 1, 1, 2, 3 }
{ 1, 1, 2, 3, 3 }
{ 1, 1, 2, 3, 3, 3 }
{ 1, 1, 3 }
{ 1, 1, 3, 2 }
{ 1, 1, 3, 2, 3 }
{ 1, 1, 3, 2, 3, 3 }
{ 1, 1, 3, 3 }
{ 1, 1, 3, 3, 2 }
{ 1, 1, 3, 3, 2, 3 }
{ 1, 1, 3, 3, 3 }
{ 1, 1, 3, 3, 3, 2 }
{ 1, 2 }
{ 1, 2, 1 }
{ 1, 2, 1, 3 }
{ 1, 2, 1, 3, 3 }
{ 1, 2, 1, 3, 3, 3 }
{ 1, 2, 3 }
{ 1, 2, 3, 1 }
{ 1, 2, 3, 1, 3 }
{ 1, 2, 3, 1, 3, 3 }
{ 1, 2, 3, 3 }
{ 1, 2, 3, 3, 1 }
{ 1, 2, 3, 3, 1, 3 }
{ 1, 2, 3, 3, 3 }
{ 1, 2, 3, 3, 3, 1 }
{ 1, 3 }
{ 1, 3, 1 }
{ 1, 3, 1, 2 }
{ 1, 3, 1, 2, 3 }
{ 1, 3, 1, 2, 3, 3 }
{ 1, 3, 1, 3 }
{ 1, 3, 1, 3, 2 }
{ 1, 3, 1, 3, 2, 3 }
{ 1, 3, 1, 3, 3 }
{ 1, 3, 1, 3, 3, 2 }
{ 1, 3, 2 }
{ 1, 3, 2, 1 }
{ 1, 3, 2, 1, 3 }
{ 1, 3, 2, 1, 3, 3 }
{ 1, 3, 2, 3 }
{ 1, 3, 2, 3, 1 }
{ 1, 3, 2, 3, 1, 3 }
{ 1, 3, 2, 3, 3 }
{ 1, 3, 2, 3, 3, 1 }
{ 1, 3, 3 }
{ 1, 3, 3, 1 }
{ 1, 3, 3, 1, 2 }
{ 1, 3, 3, 1, 2, 3 }
{ 1, 3, 3, 1, 3 }
{ 1, 3, 3, 1, 3, 2 }
{ 1, 3, 3, 2 }
{ 1, 3, 3, 2, 1 }
{ 1, 3, 3, 2, 1, 3 }
{ 1, 3, 3, 2, 3 }
{ 1, 3, 3, 2, 3, 1 }
{ 1, 3, 3, 3 }
{ 1, 3, 3, 3, 1 }
{ 1, 3, 3, 3, 1, 2 }
{ 1, 3, 3, 3, 2 }
{ 1, 3, 3, 3, 2, 1 }
{ 2 }
{ 2, 1 }
{ 2, 1, 1 }
{ 2, 1, 1, 3 }
{ 2, 1, 1, 3, 3 }
{ 2, 1, 1, 3, 3, 3 }
{ 2, 1, 3 }
{ 2, 1, 3, 1 }
{ 2, 1, 3, 1, 3 }
{ 2, 1, 3, 1, 3, 3 }
{ 2, 1, 3, 3 }
{ 2, 1, 3, 3, 1 }
{ 2, 1, 3, 3, 1, 3 }
{ 2, 1, 3, 3, 3 }
{ 2, 1, 3, 3, 3, 1 }
{ 2, 3 }
{ 2, 3, 1 }
{ 2, 3, 1, 1 }
{ 2, 3, 1, 1, 3 }
{ 2, 3, 1, 1, 3, 3 }
{ 2, 3, 1, 3 }
{ 2, 3, 1, 3, 1 }
{ 2, 3, 1, 3, 1, 3 }
{ 2, 3, 1, 3, 3 }
{ 2, 3, 1, 3, 3, 1 }
{ 2, 3, 3 }
{ 2, 3, 3, 1 }
{ 2, 3, 3, 1, 1 }
{ 2, 3, 3, 1, 1, 3 }
{ 2, 3, 3, 1, 3 }
{ 2, 3, 3, 1, 3, 1 }
{ 2, 3, 3, 3 }
{ 2, 3, 3, 3, 1 }
{ 2, 3, 3, 3, 1, 1 }
{ 3 }
{ 3, 1 }
{ 3, 1, 1 }
{ 3, 1, 1, 2 }
{ 3, 1, 1, 2, 3 }
{ 3, 1, 1, 2, 3, 3 }
{ 3, 1, 1, 3 }
{ 3, 1, 1, 3, 2 }
{ 3, 1, 1, 3, 2, 3 }
{ 3, 1, 1, 3, 3 }
{ 3, 1, 1, 3, 3, 2 }
{ 3, 1, 2 }
{ 3, 1, 2, 1 }
{ 3, 1, 2, 1, 3 }
{ 3, 1, 2, 1, 3, 3 }
{ 3, 1, 2, 3 }
{ 3, 1, 2, 3, 1 }
{ 3, 1, 2, 3, 1, 3 }
{ 3, 1, 2, 3, 3 }
{ 3, 1, 2, 3, 3, 1 }
{ 3, 1, 3 }
{ 3, 1, 3, 1 }
{ 3, 1, 3, 1, 2 }
{ 3, 1, 3, 1, 2, 3 }
{ 3, 1, 3, 1, 3 }
{ 3, 1, 3, 1, 3, 2 }
{ 3, 1, 3, 2 }
{ 3, 1, 3, 2, 1 }
{ 3, 1, 3, 2, 1, 3 }
{ 3, 1, 3, 2, 3 }
{ 3, 1, 3, 2, 3, 1 }
{ 3, 1, 3, 3 }
{ 3, 1, 3, 3, 1 }
{ 3, 1, 3, 3, 1, 2 }
{ 3, 1, 3, 3, 2 }
{ 3, 1, 3, 3, 2, 1 }
{ 3, 2 }
{ 3, 2, 1 }
{ 3, 2, 1, 1 }
{ 3, 2, 1, 1, 3 }
{ 3, 2, 1, 1, 3, 3 }
{ 3, 2, 1, 3 }
{ 3, 2, 1, 3, 1 }
{ 3, 2, 1, 3, 1, 3 }
{ 3, 2, 1, 3, 3 }
{ 3, 2, 1, 3, 3, 1 }
{ 3, 2, 3 }
{ 3, 2, 3, 1 }
{ 3, 2, 3, 1, 1 }
{ 3, 2, 3, 1, 1, 3 }
{ 3, 2, 3, 1, 3 }
{ 3, 2, 3, 1, 3, 1 }
{ 3, 2, 3, 3 }
{ 3, 2, 3, 3, 1 }
{ 3, 2, 3, 3, 1, 1 }
{ 3, 3 }
{ 3, 3, 1 }
{ 3, 3, 1, 1 }
{ 3, 3, 1, 1, 2 }
{ 3, 3, 1, 1, 2, 3 }
{ 3, 3, 1, 1, 3 }
{ 3, 3, 1, 1, 3, 2 }
{ 3, 3, 1, 2 }
{ 3, 3, 1, 2, 1 }
{ 3, 3, 1, 2, 1, 3 }
{ 3, 3, 1, 2, 3 }
{ 3, 3, 1, 2, 3, 1 }
{ 3, 3, 1, 3 }
{ 3, 3, 1, 3, 1 }
{ 3, 3, 1, 3, 1, 2 }
{ 3, 3, 1, 3, 2 }
{ 3, 3, 1, 3, 2, 1 }
{ 3, 3, 2 }
{ 3, 3, 2, 1 }
{ 3, 3, 2, 1, 1 }
{ 3, 3, 2, 1, 1, 3 }
{ 3, 3, 2, 1, 3 }
{ 3, 3, 2, 1, 3, 1 }
{ 3, 3, 2, 3 }
{ 3, 3, 2, 3, 1 }
{ 3, 3, 2, 3, 1, 1 }
{ 3, 3, 3 }
{ 3, 3, 3, 1 }
{ 3, 3, 3, 1, 1 }
{ 3, 3, 3, 1, 1, 2 }
{ 3, 3, 3, 1, 2 }
{ 3, 3, 3, 1, 2, 1 }
{ 3, 3, 3, 2 }
{ 3, 3, 3, 2, 1 }
{ 3, 3, 3, 2, 1, 1 }
Related
Convert list of integers (IEnumerable<int>) to list of tuples (IEnumerable<IEnumerable<int>>) of specific length
I try to solve next exercise: Input: List of integers with count >= 1; some positive integer k Output: all possible tuples of this integers with length of k; For instance Input: {1, 2}; k = 4 Output: { {1, 1, 1, 1}, {1, 1, 1, 2}, {1, 1, 2, 1}, {1, 1, 2, 2}, {1, 2, 1, 1}, {1, 2, 1, 2}, {1, 2, 2, 1}, {1, 2, 2, 2}, {2, 1, 1, 1}, {2, 1, 1, 2}, {2, 1, 2, 1}, {2, 1, 2, 2}, {2, 2, 1, 1}, {2, 2, 1, 2}, {2, 2, 2, 1}, {2, 2, 2, 2} } I tried to create an array that contains k copies of input list and than use Combinations: public static IEnumerable<IEnumerable<T>> Combinations<T>( this IEnumerable<T> elements, int k) { return k == 0 ? new[] { new T[0] } : elements.SelectMany((e, i) => elements .Skip(i + 1) .Combinations(k - 1) .Select(c => (new[] { e }).Concat(c))); } But it takes too long when k > 9. Is there an algorithm for solving this problem in a short time?
Let's get rid of recursion and have 512 items: Code: //TODO: you may want to declare it as IEnumerable<T[]> Combinations<T> public static IEnumerable<IEnumerable<T>> Combinations<T>( this IEnumerable<T> elements, int k) { if (null == elements) throw new ArgumentNullException(nameof(elements)); else if (k < 0) throw new ArgumentOutOfRangeException(nameof(k)); T[] alphabet = elements.ToArray(); // Special cases if (alphabet.Length <= 0) yield break; else if (k == 0) yield break; int[] indexes = new int[k]; do { yield return indexes .Select(i => alphabet[i]) .ToArray(); for (int i = indexes.Length - 1; i >= 0; --i) if (indexes[i] >= alphabet.Length - 1) indexes[i] = 0; else { indexes[i] += 1; break; } } while (!indexes.All(index => index == 0)); } Demo: string report = string.Join(Environment.NewLine, Combinations(new int[] { 1, 2}, 9) .Select(line => string.Join(", ", line))); Console.Write(report); Outcome: (512 records) 1, 1, 1, 1, 1, 1, 1, 1, 1 1, 1, 1, 1, 1, 1, 1, 1, 2 1, 1, 1, 1, 1, 1, 1, 2, 1 1, 1, 1, 1, 1, 1, 1, 2, 2 1, 1, 1, 1, 1, 1, 2, 1, 1 1, 1, 1, 1, 1, 1, 2, 1, 2 1, 1, 1, 1, 1, 1, 2, 2, 1 1, 1, 1, 1, 1, 1, 2, 2, 2 1, 1, 1, 1, 1, 2, 1, 1, 1 ... 2, 2, 2, 2, 2, 2, 1, 2, 1 2, 2, 2, 2, 2, 2, 1, 2, 2 2, 2, 2, 2, 2, 2, 2, 1, 1 2, 2, 2, 2, 2, 2, 2, 1, 2 2, 2, 2, 2, 2, 2, 2, 2, 1 2, 2, 2, 2, 2, 2, 2, 2, 2 Let's generate, say, all 2**20 == 1048576 items (k = 20), i.e. more than 1 million arrays of size 20 : Stopwatch sw = new Stopwatch(); sw.Start(); int count = Combinations(new int[] { 1, 2 }, 20).Count(); sw.Stop(); Console.Write($"{count.ToString()} items at {sw.ElapsedMilliseconds:f0} milliseconds"); Outcome: 1048576 items at 469 milliseconds
Copy part of 3-d array to 2-d array
Let's say I have a multidimensional array: var arr = new double[2, 5, 5] { { { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 } }, { { 1, 1, 1, 1, 1 }, { 1, 2, 2, 2, 1 }, { 1, 2, 2, 2, 1 }, { 1, 2, 2, 2, 1 }, { 1, 1, 1, 1, 1 } }, }; I want to copy 3 by 3 part of that array starting from index [1,1,1] till index [1,3,3] (all 2 values). What is the most efficient way of doing so ? So far, I do it with a loop: var arr2 = new int[3, 3]; int x_start = 1; int y_start = 1; for (int i = 0; i < arr2.GetLength(0); i++) { for (int j = 0; j < arr2.GetLength(1); j++) { arr2[i, j] = arr[1, x_start + i, y_start + j]; } } But I wonder if there is a more efficient way of doing it ?
poke already made the same point in their comment, but this is essentially the best way of doing this. That’s the most efficient way to do it. You are using fast loops and only loop over those indexes you are interested in. - poke You could possibly cache the two GetLength() calls in an integer, but I doubt that'd make any meaningful difference in performance.
How to create single dimensional, two dimensional,three dimensional as well as multi dimensional array using C#?
I am trying to keep all the combinations (5C1, 5C2, 5C3, 5C4, 5C5) of 1,2,3,4,5 into individual array. So I need to create dynamic array using for loop in c#. Say for example, Here n = 5 and r = 1 to 5. if r = 1 then My array will be single dimensional array, when r = 2 then it will be two dimensional array, when r = 3 then three dimensional, when r = 4 then four dimensional array and it will e continued up to end of 5. My code is given below string[] ShipArrayObj; public frmResult( string[] ShipArray ) { InitializeComponent(); ShipArrayObj = ShipArray; } private void frmResult_Load(object sender, EventArgs e) { string[] arr = ShipArrayObj; int n = ShipArrayObj.Count(); for (int r = 1; r <= n; r++) { StoreCombination(arr, n, r); richTextBox1.Text = richTextBox1.Text + "/"; } } void StoreCombination(string[] arr, int n, int r) { string[] data = new string[r]; createCombination (arr, data, 0, n - 1, 0, r); } private void createCombination(string[] arr, string[] data, int start, int end, int index, int r) { if (index == r) { int j = 0; for (j = 0; j < r; j++) richTextBox1.Text = richTextBox1.Text + data[j].ToString();//Where I want to set array to keep combination values return; } int i = 0; for (i = start; i <= end && end - i + 1 >= r - index; i++) { data[index] = arr[i]; CreateCombination(arr, data, i + 1, end, index + 1, r); } } I am storing all the combination into a Rich Text Box, but want to keep into array. If anybody help me then I will be grateful to you.
If you're used to something like Java then multidimensional arrays are a little different in syntax in C#. Here's a page describing how to do them in C#. Here's a snippet from said page: // Two-dimensional array. int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // The same array with dimensions specified. int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // A similar array with string elements. string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" }, { "five", "six" } }; // Three-dimensional array. int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // The same array with dimensions specified. int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; If you're interested in different combinations of things with a fixed number of them, something like this should be all you need. If you're interested in different combinations of things with a dynamic number of them, something like this should be all you need. (Unless you're trying to optimize performance, it's better to be readable/expressive, generally speaking.) You may need to consider whether or not order matters (un-ordered set vs. ordered list). I would assume it doesn't from your code (in which case sorting is good to eliminate "duplicates"), but I can't tell for sure. Here's a good example that's easy to read and modify for variations and isn't so bad for small numbers: // -1, 0, ..., 5 var choices = Enumerable.Range(-1, 6); var possibleChoices = from a in choices from b in choices from c in choices from d in choices from e in choices select (IEnumerable<int>)new [] { a, b, c, d, e }; // Remove -1's because they represent not being in the choice. possibleChoices = possibleChoices.Select(c => c.Where(d => d >= 0)); // Remove choices that have non-unique digits. possibleChoices = possibleChoices.Where(c => c.Distinct().Count() == c.Count()); // Sort the choices to indicate order doesn't matter possibleChoices = possibleChoices.Select(c => c.OrderBy(d => d)); // Remove duplicates possibleChoices = possibleChoices.Select(c => new { Key = string.Join(",", c), Choice = c }). GroupBy(c => c.Key). Select(g => g.FirstOrDefault().Choice); foreach (var choice in possibleChoices) { Console.Out.WriteLine(string.Join(", ", choice)); } Output: 0 1 2 3 4 0, 1 0, 2 0, 3 0, 4 1, 2 1, 3 1, 4 2, 3 2, 4 3, 4 0, 1, 2 0, 1, 3 0, 1, 4 0, 2, 3 0, 2, 4 0, 3, 4 1, 2, 3 1, 2, 4 1, 3, 4 2, 3, 4 0, 1, 2, 3 0, 1, 2, 4 0, 1, 3, 4 0, 2, 3, 4 1, 2, 3, 4 0, 1, 2, 3, 4 This is probably a little more dense to understand, hard-coded to this specific variation of combination and involves recursion but is a bit more generic/isn't hard-coded to 5 (and took 0.047s on dotnetfiddle.net instead of 0.094s). It's also completely lazy/IEnumerable. public static void Main() { var possibleChoices = Choose(5); foreach (var choice in possibleChoices) { Console.Out.WriteLine(string.Join(", ", choice)); } } public static IEnumerable<IEnumerable<int>> Choose(int max) { var remaining = Enumerable.Range(0, max); return ChooseRecursive(remaining, Enumerable.Empty<int>()); } public static IEnumerable<IEnumerable<int>> ChooseRecursive(IEnumerable<int> remaining, IEnumerable<int> chosen) { yield return chosen; foreach (var digit in remaining) { var choices = ChooseRecursive( remaining.Where(d => d > digit), chosen.Concat(new [] { digit }) ); foreach (var choice in choices) { yield return choice; } } } Output: 0 0, 1 0, 1, 2 0, 1, 2, 3 0, 1, 2, 3, 4 0, 1, 2, 4 0, 1, 3 0, 1, 3, 4 0, 1, 4 0, 2 0, 2, 3 0, 2, 3, 4 0, 2, 4 0, 3 0, 3, 4 0, 4 1 1, 2 1, 2, 3 1, 2, 3, 4 1, 2, 4 1, 3 1, 3, 4 1, 4 2 2, 3 2, 3, 4 2, 4 3 3, 4 4
Array for 4 dimension initializing
An array of 3 dimensions initializes like this. int[,,] arr = new int[2,3,3] {{{1,2,3},{4,5,6},{7,8,9}}, {{1,2,3},{4,5,6},{7,8,9}}}; How do you initialize this in 4 dimensions array or more? int[,,,] arr = new int[3,6,5,2] // how to initialize as above?
If you want an example just like yours, it would be like this: int[, , ,] a = new int[2, 3, 3, 3] { { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } } }, { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } } } };
C# remove duplicates from List<List<int>>
I'm having trouble coming up with the most efficient algorithm to remove duplicates from List<List<int>>, for example (I know this looks like a list of int[], but just doing it that way for visual purposes: my_list[0]= {1, 2, 3}; my_list[1]= {1, 2, 3}; my_list[2]= {9, 10, 11}; my_list[3]= {1, 2, 3}; So the output would just be new_list[0]= {1, 2, 3}; new_list[1]= {9, 10, 11}; Let me know if you have any ideas. I would really appreciate it.
Build custom of EqualityComparer<List<int>>: public class CusComparer : IEqualityComparer<List<int>> { public bool Equals(List<int> x, List<int> y) { return x.SequenceEqual(y); } public int GetHashCode(List<int> obj) { int hashCode = 0; for (var index = 0; index < obj.Count; index++) { hashCode ^= new {Index = index, Item = obj[index]}.GetHashCode(); } return hashCode; } } Then you can get the result by using Distinct with custom comparer method: var result = my_list.Distinct(new CusComparer()); Edit: Include the index into method GetHashCode to make sure different orders will not be equal
This simple program does what you want: using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { List<List<int>> lists = new List<List<int>>(); lists.Add(new List<int> { 1, 2, 3 }); lists.Add(new List<int> { 1, 2, 3 }); lists.Add(new List<int> { 9, 10, 11 }); lists.Add(new List<int> { 1, 2, 3 }); var distinct = lists.Select(x => new HashSet<int>(x)) .Distinct(HashSet<int>.CreateSetComparer()); foreach (var list in distinct) { foreach (var v in list) { Console.Write(v + " "); } Console.WriteLine(); } } } }
var finalList = lists.GroupBy(x => String.Join(",", x)) .Select(x => x.First().ToList()) .ToList();
You can use the LINQ Distinct overload that takes a comparer. The comparer should see if the lists are equal. Note that the default equals operations of lists won't do what you're really looking for, so the comparer will need to loop through each for you. Here's an example of such a comparer: public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>> { IEqualityComparer<T> itemComparer; public SequenceComparer() { this.itemComparer = EqualityComparer<T>.Default; } public SequenceComparer(IEqualityComparer<T> itemComparer) { this.itemComparer = itemComparer; } public bool Equals(IEnumerable<T> x, IEnumerable<T> y) { if (object.Equals(x, y)) return true; if (x == null || y == null) return false; return x.SequenceEqual(y, itemComparer); } public int GetHashCode(IEnumerable<T> obj) { if (obj == null) return -1; int i = 0; return obj.Aggregate(0, (x, y) => x ^ new { Index = i++, ItemHash = itemComparer.GetHashCode(y) }.GetHashCode()); } } Update: I got the idea of using an anonymous type to make a better hash from Cuong Le's answer, and I LINQ-ified it and made it work in my class.
For small sets of data, a comparer could be useful, but if you have 1000 or more List> then trying to compare them all could begin to take a long amount of time. I suggest that you instead use your data to build a distinct tree. The building of the tree will be much faster and when you are done you can always bring your data back into your old data structure.
I wanted to compare the performance of the answers of #Leniel Macaferi and #L.B as I wasn't sure which would be more performant, or if the difference would be significant. It turns out that the difference is very significant: Method 1: 00:00:00.0976649 #Leniel Macaferi Method 2: 00:00:32.0961650 #L.B Here is the code I used to benchmark them: public static void Main(string[] args) { var list = new List<List<int>> {new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11, 1}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6, 7}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}}; var sw1 = new Stopwatch(); sw1.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.Select(x => new HashSet<int>(x)).Distinct(HashSet<int>.CreateSetComparer()); } sw1.Stop(); Console.WriteLine($"Method 1: {sw1.Elapsed}"); var sw2 = new Stopwatch(); sw2.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.GroupBy(a => string.Join(",", a)).Select(a => a.First()).ToList(); } sw2.Stop(); Console.WriteLine($"Method 2: {sw2.Elapsed}"); Console.ReadKey(); }