find 和 findindex 对于 List
我正在一个密集使用 List 的项目中工作,我尝试通过名称(即对象的成员)查找对象。
我的代码无需使用单个 for-next 循环(函数 find1)进行搜索即可工作,但我发现可以使用内置的 find find 进行相同的操作,并且代码可以工作。不过,感觉有点慢。所以,我做了一个项目来测试速度:
我有下一个代码
public List<MyObject> varbig = new List<MyObject>();
public Dictionary<string,string> myDictionary=new Dictionary<string, string>();
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
myDictionary.Clear();
varbig.Clear();
for (int i = 0; i < 5000; i++) {
varbig.Add(new MyObject("name" + i.ToString(),"value"+i.ToString()));
myDictionary.Add("name" + i.ToString(), i.ToString());
}
// first test
var start1 = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss=find1("name499");
}
var end1 = Environment.TickCount;
Console.WriteLine("time 1 :" + (end1 - start1));
// second test
var start2 = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss=find2("name499");
}
var end2 = Environment.TickCount;
Console.WriteLine("time 2 :" + (end2 - start2));
// third test
var start3 = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss = find3("name499");
}
var end3 = Environment.TickCount;
Console.WriteLine("time 3 :" + (end3 - start3));
// first test b
var start1b = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss=find1("name4999");
}
var end1b = Environment.TickCount;
Console.WriteLine("timeb 1 :" + (end1b - start1b));
// second test
var start2b = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss=find2("name4999");
}
var end2b = Environment.TickCount;
Console.WriteLine("timeb 2 :" + (end2b - start2b));
// third test
var start3b = Environment.TickCount;
for (int i = 0; i < 3000; i++) {
var ss = find3("name4999");
}
var end3b = Environment.TickCount;
Console.WriteLine("timeb 3 :" + (end3b - start3b));
}
public int find1(string name) {
for (int i = 0; i < varbig.Count; i++) {
if(varbig[i].Name == name) {
return i;
}
}
return -1;
}
public int find2(string name) {
int idx = varbig.FindIndex(tmpvar => Name == name);
return idx;
}
public int find3(string name) {
var ss=myDictionary[name];
return int.Parse(ss);
}
}
并且我使用下一个对象
public class MyObject {
private string _name = "";
private string _value = "";
public MyObject() {}
public MyObject(string name, string value) {
_name = name;
_value = value;
}
public string Name {
get { return _name; }
set { _name = value; }
}
public string Value {
get { return _value; }
set { _value = value; }
}
}
大多数情况下它会做接下来的事情: 我创建了一个包含 5000 个元素的数组。
time 1 = 使用简单的 for-next 搜索第 499 个对象(索引)。
时间 2 = 使用 List 的内置函数 find 搜索第 499 个元素
时间 3 = 使用字典搜索第 499 个元素。
Timeb 1、timeb 2 和 timeb 3 执行相同操作,但尝试搜索第 4999 个元素而不是第 499 个元素。
我跑了几次:
- time 1 :141
- time 2 :1248
- time 3 :0
- timeb 1 :811
- timeb 2 :1170
-
timeb 3 :0
-
time 1 :109< /p>
- 时间 2:1170
- 时间 3:0
- 时间b 1:796
- timeb 2 :1170
- timeb 3 :0
(越小则越快)
而且,令我惊讶的是,内置函数 findindex 慢得离谱(在某些情况下,接近慢 10 倍,而且,字典方法几乎是即时的。
我的问题是,为什么?是因为谓词吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题出在这一行:
Name == name
是错误的,你应该写tmpvar.Name == name
。在您的代码中,您将
name
参数与表单的Name
属性进行比较;它们显然是不同的,因此该方法总是检查整个列表,而不是在找到搜索值时停止。事实上,正如您从数字中看到的那样,find2()
花费的时间基本上总是相等的。关于字典,它显然比其他方法更快,因为字典是专门为提供快速键控访问而构建的内存结构。
事实上,它们的时间复杂度接近
O(1)
,而循环列表时,时间复杂度等于O(n)
。The problem is in this line:
Name == name
is wrong, you should writetmpvar.Name == name
instead.In your code you're comparing
name
argument with theName
property of your form; they are obviously different, and so the method always examines the whole list instead of stopping when the searched value is found. In fact, as you can see looking the numbers, the time spent byfind2()
is basically always equal.About the dictionary, it's obviously faster than the other methods because dictionaries are memory structure specifically built to provide fast keyed access.
In fact they arrive close to
O(1)
time complexity, while looping a list you have a time complexity equal toO(n)
.您的代码中存在错误 -
find2
方法使用 Form.Name 进行比较,而不是您的集合对象名称。它应该看起来像这样:不使用 Form.Name 的结果更加一致:
There is the error in your code - the
find2
method uses the Form.Name for the comparison instead of your collection objects names. It should looks like this:The results without using the Form.Name are more consistent:
您不需要使用
for
循环在find2
中进行搜索...只需直接调用
find2
,结果将为 0。You don't need to put
for
loop to search infind2
...Just call
find2
directly, then result will be 0.