2015-04-04 113 views
1

这是我的第一个问题,所以我希望我做对了。
我要创建整数阵列的列表:以存储与N个数K中的元素的所有组合搜索列表中的现有对象

List<int[]> finalList = new List<int[]>(); 

例如:

N=5, K=2 => {1,2},{1,3},{1,4},... 

一切都是正确的,但我想避免的名单({1,2}{2,1}例如)同一组合的重复。因此,在将tmpArray(其中我临时存储新组合)添加到列表中之前,我想检查它是否已经存储。

这是我在做什么:

  • 下一个组合(OK)
  • 排序tmpArray(OK)
  • 检查创建tmpArray如果列表中已经包含tmpArray具有以下代码:

    if (!finalList.Contains(tmpArray)) 
        finalList.Add(tmpArray); 
    

,但它不工作。任何人都可以帮我解决这个问题吗?

+0

你考虑避免在首位的重复?例如。只添加n1 CompuChip 2015-04-04 15:30:36

回答

1

Array是一个引用类型 - 你的Contains查询不会做你想做的(比较所有成员的顺序)。

你可以使用这样的事情:

if (!finalList.Any(x => x.SequenceEqual(tmpArray)) 
{ 
    finalList.Add(tmpArray); 
} 

(请确保您添加using System.Linq到文件的顶部)

我建议你了解value vs. reference types,LINQ和C#的数据结构基础。尽管上面的查询应该可以工作,但它会很慢 - O(n * m)其中n =每个阵列的finalListm长度中的数组数量。

对于较大的数组,某些预计算(例如每个数组的哈希码)允许您进行更快速的比较可能会有所帮助。

+0

当我更多地了解可以完成许多不同事情的Linqs和Lambda表达式时,我越来越惊讶。你的例子是否与TakeWhile()相似?我以前用它来做数组比较。 – Shar1er80 2015-04-04 14:54:01

+0

@ Shar1er80类似的,它遍历一个枚举,是的 - 否则不同 – BrokenGlass 2015-04-04 16:10:19

0

如果我没有记错,包含将检查值数据类型的值,或者它将检查对象类型的地址。一个数组是一个对象类型,所以这个contains只检查内存中的地址是否存储在你的列表中。您必须检查此列表中的每个项目并执行某种类型的算法以检查数组值是否在列表中。

Linq,Lambda或蛮力检查浮现在脑海。

BrokenGlass对Linq和Lambda给出了一个很好的建议。

蛮力:

bool itemExists = true; 
foreach (int[] ints in finalList) 
{ 
    if (ints.Length != tmpArray.Length) 
    { 
     itemExists = false; 
     break; 
    } 
    else 
    { 
     // Compare each element 
     for (int i = 0; i < tmpArray.Length; i++) 
     { 
      if (ints[i] != tmpArray[i]) 
      { 
       itemExists = false; 
       break; 
      } 
     } 

     // Have to check to break from the foreach loop 
     if (itemExists == false) 
     { 
      break; 
     } 
    } 
} 

if (itemExists == false) 
{ 
    finalList.add(tmpArray); 
} 
+1

有一个'Contains'的重载,它需要'IEqualityComparer'来进行比较。如果没有提供,则使用默认的相等比较器,其语义如下所述:https://msdn.microsoft.com/en-us/library/vstudio/ms224763(v=vs.100).aspx。 – 2015-04-04 15:09:13