我希望有人能帮助我,至少对我来说,这是一个非常棘手的算法。
我有一个列表(1 <= size <= 5
,但在运行时大小未知)我需要合并的列表(1 <= size <= 2
)。这是我正在看的一个例子: -
ListOfLists = { {1}, {2,3}, {2,3}, {4}, {2,3} }
因此,我需要做两个阶段: -
(1)。我需要以这样的方式组合内部列表:任何组合都有来自每个列表的一个项目,也就是说,结果集中的可能组合将是: -
Cartesian产品负责这一点,因此第1阶段已经完成.....现在,这里出现了我无法弄清楚的扭曲 - 至少我无法弄清楚LINQ的做法(我仍然是LINQ菜鸟。
(2)。我现在需要过滤掉这个笛卡尔积的任何重复结果。在这种情况下,副本构成结果集中的任何行,每个不同的列表元素的数量与另一行相同,即
<1,2> 1,2,3与1,3,2,4,2 “相同”因为第一个列表中的每个不同项目在两个列表中出现的次数相同(1个在每个列表中出现一次,2个在每个列表中出现两次,....
因此,最终结果集应如下所示......
另一个例子是最坏情况(从组合的角度来看),其中ListOfLists是{{2,3},{2,3},{2,3},{2,3},{2 ,3}},即包含最大大小的内部列表的列表 - 在这种情况下,笛卡尔积结果集中显然会有32个结果,但我想要得到的修剪结果集只是: -
对于任何有数学头脑的人 - 我希望你能提供帮助。我实际上已经有了第2部分的工作解决方案,但这是一个完全的黑客攻击并且计算量很大,我正在寻找指导,以便为修剪问题找到更优雅,更有效的LINQ解决方案。
感谢阅读。
PIP
到目前为止使用的一些资源(获取笛卡尔积)
抱歉没有尽早发布此信息......请参阅below
答案 0 :(得分:3)
您应该实现自己的IEqualityComparer<IEnumerable<int>>
,然后在Distinct()
中使用它。
IEqualityComparer
中哈希码的选择取决于您的实际数据,但如果您的实际数据与示例中的数据类似,我认为这样的内容应该足够了:
class UnorderedQeuenceComparer : IEqualityComparer<IEnumerable<int>>
{
public bool Equals(IEnumerable<int> x, IEnumerable<int> y)
{
return x.OrderBy(i => i).SequenceEqual(y.OrderBy(i => i));
}
public int GetHashCode(IEnumerable<int> obj)
{
return obj.Sum(i => i * i);
}
}
重要的一点是GetHashCode()
应该是O(N),排序会太慢。
答案 1 :(得分:1)
void Main()
{
var query = from a in new int[] { 1 }
from b in new int[] { 2, 3 }
from c in new int[] { 2, 3 }
from d in new int[] { 4 }
from e in new int[] { 2, 3 }
select new int[] { a, b, c, d, e };
query.Distinct(new ArrayComparer());
//.Dump();
}
public class ArrayComparer : IEqualityComparer<int[]>
{
public bool Equals(int[] x, int[] y)
{
if (x == null || y == null)
return false;
return x.OrderBy(i => i).SequenceEqual<int>(y.OrderBy(i => i));
}
public int GetHashCode(int[] obj)
{
if ( obj == null || obj.Length == 0)
return 0;
var hashcode = obj[0];
for (int i = 1; i < obj.Length; i++)
{
hashcode ^= obj[i];
}
return hashcode;
}
}
答案 2 :(得分:1)
整个组合多个集合的最终解决方案,然后修剪结果集以删除重复问题最终作为静态方法在辅助类中结束。它需要svick非常赞赏的答案并将IEqualityComparer依赖注入我在Eric Lipperts的博客here中发现的现有CartesianProduct答案(我建议阅读他的帖子,因为它解释了他思考中的迭代以及为什么linq implimentation是最好)。
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences,
IEqualityComparer<IEnumerable<T>> sequenceComparer)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
var resultsSet = sequences.Aggregate(emptyProduct, (accumulator, sequence) => from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
if (sequenceComparer != null)
return resultsSet.Distinct(sequenceComparer);
else
return resultsSet;
}