Algorithm 唯一组合算法
我一直在试图找到一种方法,从嵌套在容器中的对象列表中获取唯一组合的列表。不能合并同一组中的对象。对象在所有组中都是唯一的 例如:Algorithm 唯一组合算法,algorithm,combinations,Algorithm,Combinations,我一直在试图找到一种方法,从嵌套在容器中的对象列表中获取唯一组合的列表。不能合并同一组中的对象。对象在所有组中都是唯一的 例如: Group 1: (1,2) Group 2: (3,4) 结果 1 2 3 4 1,3 1,4 2,3 2,4 如果我们添加另一个类似的组: Group 1: (1,2) Group 2: (3,4) Group 3: (5,6,7) 结果将是 1 2 3 4 5 6 7 1,3 1,4 1,5 1,6 1,7 2,3 2,4 2,5 2,6 2,7 3,5
Group 1: (1,2)
Group 2: (3,4)
结果
1
2
3
4
1,3
1,4
2,3
2,4
如果我们添加另一个类似的组:
Group 1: (1,2)
Group 2: (3,4)
Group 3: (5,6,7)
结果将是
1
2
3
4
5
6
7
1,3
1,4
1,5
1,6
1,7
2,3
2,4
2,5
2,6
2,7
3,5
3,6
3,7
4,5
4,6
4,7
1,3,5
1,3,6
1,3,7
1,4,5
1,4,6
1,4,7
2,3,5
2,3,6
2,3,7
2,4,5
2,4,6
2,4,7
我可能错过了上面的一个组合,但上面提到的组合应该足以说明问题
我有可能有7组,每个对象20组
我试图避免让代码知道它是在做双倍、三倍、四倍等的组合,但在这过程中我遇到了很多逻辑障碍
明确地说,我不是在要求代码,更多的是一种方法,伪代码或指示将非常有用
更新
这是我看到这两个答案后得到的
来自@Servy的回答:
public static IEnumerable<IEnumerable<T>> GetCombinations<T>(this IEnumerable<IEnumerable<T>> sequences)
{
var defaultArray = new[] { default(T) };
return sequences.Select(sequence =>
sequence.Select(item => item).Concat(defaultArray))
.CartesianProduct()
.Select(sequence =>
sequence.Where(item => !item.Equals(default(T)))
.Select(item => item));
}
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item })
);
}
公共静态IEnumerable GetCombinations(此IEnumerable序列)
{
var defaultArray=new[]{default(T)};
返回序列。选择(序列=>
sequence.Select(item=>item.Concat(defaultArray))
.CartesianProduct()
.选择(序列=>
sequence.Where(item=>!item.Equals(默认值(T)))
.选择(项目=>项目));
}
公共静态IEnumerable CartesianProduct(此IEnumerable序列)
{
IEnumerable emptyProduct=new[]{Enumerable.Empty()};
返回序列.聚合(
空产品,
(累加器,顺序)=>
来自蓄能器中的accseq
按顺序从项目开始
选择accseq.Concat(新[]{item})
);
}
来自@AK_uz的回答
public static IEnumerable<IEnumerable<T>> GetCombinations<T>(this IEnumerable<IEnumerable<T>> groups)
{
if (groups.Count() == 0)
{
yield return new T[0];
}
if (groups.Count() == 1)
{
foreach (var t in groups.First())
{
yield return new T[] { t };
}
}
else
{
var furtherResult = GetCombinations(groups.Where(x => x != groups.Last()));
foreach (var result in furtherResult)
{
yield return result;
}
foreach (var t in groups.Last())
{
yield return new T[] { t };
foreach (var result in furtherResult)
{
yield return result.Concat(new T[] { t });
}
}
}
}
公共静态IEnumerable GetCombinations(此IEnumerable组)
{
如果(groups.Count()==0)
{
收益率-收益率新T[0];
}
if(groups.Count()==1)
{
foreach(组中的var t.First())
{
产生返回新的T[]{T};
}
}
其他的
{
var-furtherResult=getcombines(groups.Where(x=>x!=groups.Last());
foreach(进一步结果中的var结果)
{
收益结果;
}
foreach(组中的var t.Last())
{
产生返回新的T[]{T};
foreach(进一步结果中的var结果)
{
产生返回结果.Concat(新的T[]{T});
}
}
}
}
两者的用法
List<List<int>> groups = new List<List<int>>();
groups.Add(new List<int>() { 1, 2 });
groups.Add(new List<int>() { 3, 4, 5 });
groups.Add(new List<int>() { 6, 7 });
groups.Add(new List<int>() { 8, 9 });
groups.Add(new List<int>() { 10, 11 });
var x = groups.GetCombinations().Where(g => g.Count() > 0).ToList().OrderBy(y => y.Count());
列表组=新列表();
添加(新列表(){1,2});
添加(新列表(){3,4,5});
添加(新列表(){6,7});
添加(新列表(){8,9});
添加(新列表(){10,11});
var x=groups.getcombines().Where(g=>g.Count()>0.ToList().OrderBy(y=>y.Count());
什么是最佳解决方案?老实说,我能够阅读AKY的解决方案所发生的事情要容易得多(必须寻找一个如何得到笛卡尔积的解决方案)。也就是说,每个序列中一个值的每个组合 但是我们如何处理输出组合的大小小于序列数的情况呢?它只处理给定序列的大小与序列数相同的情况。好吧,想象一下,每一个输入序列都有一个“空”值。该空值与来自其他序列(包括其所有空值)的每个值组合成对。然后我们可以在最后删除这些空值,瞧,我们有各种大小的组合 为此,在仍然允许输入序列实际使用C#literal
null
值或该类型的默认值(如果不可为null)的同时,我们需要包装该类型。我们将创建一个包装器来包装实际值,同时也有自己的def-ult/null值定义。从那里,我们将每个序列映射到一个包装器序列中,将实际默认值附加到末尾,计算笛卡尔积,然后将组合映射回“真实”值,在处理时过滤掉默认值
如果您不想看到实际的代码,请停止阅读此处
公共类包装器
{
公共包装器(T值){value=value;}
公共静态包装默认值=新包装(默认值(T));
公共T值{get;私有集;}
}
公共静态IEnumerable Foo
(这是不可数序列)
{
返回序列。选择(序列=>
sequence.Select(item=>newwrapper(item))
.Concat(新[]{Wrapper.Default}))
.CartesianProduct()
.选择(序列=>
sequence.Where(wrapper=>wrapper!=wrapper.Default)
.Select(wrapper=>wrapper.Value));
}
在C语言中#
这实际上是一个单子。。。我想
IEnumerable<IEnumerable<int>> foo (IEnumerable<IEnumerable<int>> groups)
{
if (groups.Count == 0)
{
return new List<List<int>>();
}
if (groups.Count == 1)
{
foreach(van num in groups.First())
{
return yield new List<int>(){num};
}
}
else
{
var furtherResult = foo(groups.Where(x=> x != groups.First()));
foreach (var result in furtherResult)
{
yield return result;
}
foreach(van num in groups.First())
{
yield return new List<int>(){num};
foreach (var result in furtherResult)
{
yield return result.Concat(num);
}
}
}
}
IEnumerable foo(IEnumerable组)
{
如果(groups.Count==0)
{
返回新列表();
}
如果(groups.Count==1)
{
foreach(组中的van num.First())
{
返回yield new List(){num};
}
}
其他的
{
var-furtherResult=foo(groups.Where(x=>x!=groups.First());
foreach(进一步结果中的var结果)
{
收益结果;
}
foreach(组中的van num.First())
{
返回新列表(){num};
foreach(进一步结果中的var结果)
{
收益率返回结果。Concat(num);
}
}
}
}
更好的版本:
public static IEnumerable<IEnumerable<T>> foo<T> (IEnumerable<IEnumerable<T>> groups)
{
if (groups.Count() == 0)
{
return new List<List<T>>();
}
else
{
var firstGroup = groups.First();
var furtherResult = foo(groups.Skip(1));
IEnumerable<IEnumerable<T>> myResult = from x in firstGroup
select new [] {x};
myResult = myResult.Concat( from x in firstGroup
from result in furtherResult
select result.Concat(new T[]{x}));
myResult = myResult.Concat(furtherResult);
return myResult;
}
}
公共静态IEnumerable foo(IEnumerabl
IEnumerable<IEnumerable<int>> foo (IEnumerable<IEnumerable<int>> groups)
{
if (groups.Count == 0)
{
return new List<List<int>>();
}
if (groups.Count == 1)
{
foreach(van num in groups.First())
{
return yield new List<int>(){num};
}
}
else
{
var furtherResult = foo(groups.Where(x=> x != groups.First()));
foreach (var result in furtherResult)
{
yield return result;
}
foreach(van num in groups.First())
{
yield return new List<int>(){num};
foreach (var result in furtherResult)
{
yield return result.Concat(num);
}
}
}
}
public static IEnumerable<IEnumerable<T>> foo<T> (IEnumerable<IEnumerable<T>> groups)
{
if (groups.Count() == 0)
{
return new List<List<T>>();
}
else
{
var firstGroup = groups.First();
var furtherResult = foo(groups.Skip(1));
IEnumerable<IEnumerable<T>> myResult = from x in firstGroup
select new [] {x};
myResult = myResult.Concat( from x in firstGroup
from result in furtherResult
select result.Concat(new T[]{x}));
myResult = myResult.Concat(furtherResult);
return myResult;
}
}