C#更快的方法来过滤带有int数组作为索引的循环?

时间:2019-04-24 07:40:23

标签: c# arrays performance

对不起,如果重复的话,这里的第一个问题...

我想对称为笔记的大量结构进行操作。 但是我不想对音符的每个元素进行操作。我试图使用一个filter的int数组(int[])来跳过很多代码,如下面的代码所示。

Note[] notes = new Note[]
{ 
   // Struct stuff ... 
};

int[] filter = new int[]{ 4,20,50,367... };

for (int i = 0; i < notes.Length; i++)
{
     bool flag = false;
     for (int j = 0; j < filter.Length; j++)
     {
          if (i == filter[j])
          {
               flag = true;
               break;
          }
      }

      if (flag) continue;
      // Do something on notes[i]
}

问题是,当notes数组和filter数组都扩展时,代码将运行真的很慢(我认为)。 因此,是否有更好且更快的方法来做到这一点?请注意,过滤器的大小可以根据其他条件而定

3 个答案:

答案 0 :(得分:2)

我们可以借助boost摆脱内循环,同时拥有更好的HashSet<int> 时间复杂度而不是初始{{1 }}:

O(|filter| + |notes|)

答案 1 :(得分:1)

您可以像这样使用Linq过滤笔记:

Note[] notes = new Note[]{ ...//Struct stuff };
int[] filter = new int[]{ 4,20,50,367... };

var filteredNotes = notes.ToList().Where(note => !filter.Contains(note.Id)).ToList();

foreach(var note in filteredNotes)
{
//Do something on note
}

但是,由于Linq在特定情况下往往运行缓慢,因此您需要测试性能。

答案 2 :(得分:0)

您可以循环过滤器数组并创建一个新的布尔数组,其中包含您要跳过的所有元素为真。

bool[] filterArray= new bool[notes.Length];
foreach(var index in filter)
{
   if(index<filterArray.Length)
       filterArray[index]=true;
}

然后,您只需要检查此数组的索引即可。

for (int i = 0; i < notes.Length; i++)
{
     if(!filterArray[i]){
     //Do something on notes[i]
     }

}

此代码的复杂度将为O(m+n*X),其中m是过滤器数组的长度,n是节点数组的长度,X的复杂度notes[i]上的操作。假设mO(n * X)。

您的复杂度现在为O(m*n*X)