为什么不是';t使用FindIndex(),并比FindAll()更快地从迭代中提前返回
本文关键字:迭代 返回 FindAll 为什么不 FindIndex 使用 并比 | 更新日期: 2023-09-27 18:28:23
我需要在列表项上测试的匹配条件非常耗时。此外,我知道该条件将匹配不超过3项的列表。
因此,检查所有列表项可能不是最好的主意;然而,当我尝试最多使用FindFindex()
方法3次时,测试比我使用FindAll()
和Where()
的情况花费更多。
我如何加快这种方法的速度,或者最多能更快地找到三个匹配?
| # Method Time (sec)
| -------------------------------
| 1 Find (one-by-one) 42.37
| 2 FindAll 30.17
| 3 Where 30.53
方法#1:
{
int index;
Predicate<T> predicate = t =>
{
...
};
index = myCollection.FindIndex(predicate);
if (index != -1)
{
T t1 = myCollection[index];
myCollection.RemoveAt(index);
index = myCollection.FindIndex(predicate);
if (index != -1)
{
T t2 = myCollection[index];
myCollection.RemoveAt(index);
index = myCollection.FindIndex(predicate);
if (index != -1)
{
T t3 = myCollection[index];
return new T[] { t1, t2, t3 };
}
else
{
return new T[] { t1, t2 };
}
}
else
{
return new T[] { t1 };
}
}
else
{
return new T[] { };
}
}
方法#2:
{
return myCollection.FindAll(t =>
{
...
}).ToArray();
}
方法#3:
{
return myCollection.Where(t =>
{
...
}).ToArray();
}
编辑:修改方法#1:
{
int index;
Predicate<T> predicate = t =>
{
...
};
index = myCollection.FindIndex(predicate);
if (index != -1)
{
T t1 = myCollection[index];
index = myCollection.FindIndex(index + 1, predicate);
if (index != -1)
{
T t2 = myCollection[index];
index = myCollection.FindIndex(index + 1, predicate);
if (index != -1)
{
T t3 = myCollection[index];
return new T[] { t1, t2, t3 };
}
else
{
return new T[] { t1, t2 };
}
}
else
{
return new T[] { t1 };
}
}
else
{
return new T[] { };
}
}
您的方法较慢,因为它在整个集合上迭代三次,而且您执行的删除操作也会受到惩罚(根据MSDN,为"O(n),其中n是(计数-索引)")。
您可以通过调用FindIndex(int, predicate)
重载来避免这两种情况,其中int
在迭代源集合时终止起始位置。
因此,更换出现这种情况的两个位置:
myCollection.RemoveAt(index);
index = myCollection.FindIndex(predicate);
有了这个:
index = myCollection.FindIndex(index + 1, predicate)
只要使用List,就没有办法,只能在集合中迭代。你可以修改#3如下:
return myCollection.Where(...).Take(3).ToArray();
ToArray将开始迭代,take 3将限制迭代在3个结果之后停止。这与您的#1(修改后的)示例实际上是一样的。
编辑:
以下是关于Take工作行为的Linqpad测试程序:
void Main()
{
var list = new List<Something>();
for(int i=0; i<100; i++)
list.Add(new Something { Value = i });
var result = list.Where(p => p.Value < 50).Take(3);
result.Count().Dump();
}
public class Something
{
private int _value;
public int Value
{
get { _value.Dump(); return _value; }
set { _value = value; }
}
}
测试结果:
0
1
2
3
最后一个是集合计数,只枚举了3项。