[英]Faster way to filter a list of objects in to another list based on a condition
I have a list ( ios contacts ) which i need to filter based on the firstname , last name and email starting with the match string. 我有一个列表(ios联系人),我需要根据匹配字符串开头的名字,姓氏和电子邮件进行过滤。 I have about 5000 contacts and currently it takes about 2 seconds to filter results.
我有大约5000个联系人,目前大约需要2秒钟来过滤结果。 Here is my code.
这是我的代码。
var personList = people.FindAll (p =>
(p.LastName != null && p.LastName.IndexOf (findstr, StringComparison.OrdinalIgnoreCase) == 0) || (p.FirstName != null && p.FirstName.IndexOf (findstr, StringComparison.OrdinalIgnoreCase) == 0
|| (p.GetEmails ().ToList ().Count > 0 && (p.GetEmails ().ToList ().FindAll (e => e.Value.IndexOf (findstr, StringComparison.OrdinalIgnoreCase) == 0).Count > 0)))
);
Can anyone suggest a faster way to do this? 谁能建议一个更快的方法来做到这一点? Thanks
谢谢
Instead of FindAll
, and calls to ToList
and then Count
, use: 代替
FindAll
,先调用ToList
然后再调用Count
,请使用:
var personList = people.Where(p => (p.LastName != null
&& p.LastName.IndexOf(findstr, StringComparison.OrdinalIgnoreCase) == 0)
|| (
p.FirstName != null && p.FirstName.IndexOf(findstr, StringComparison.OrdinalIgnoreCase) == 0
|| (p.GetEmails().Count > 0 && (p.GetEmails()
.Where(e =>
e.Value.IndexOf(findstr, StringComparison.OrdinalIgnoreCase) == 0).Count > 0))
));
Using IndexOf(..) == 0
to compare is the same as asking if that string (Name, LastName or Email) starts with the given findstr
. 使用
IndexOf(..) == 0
进行比较与询问该字符串(名称,姓氏或电子邮件)是否以给定的findstr
开头相同。 If instead you want to know if the string contains de findstr
use the String.Contains
or IndexOf(..) != -1
相反,如果您想知道字符串是否包含
findstr
使用String.Contains
或IndexOf(..) != -1
I would also separate those predicates for code clarity like this: 为了简化代码,我还将这些谓词分开:
Func<string, bool> filter = s => !String.IsNullOrWhiteSpace(s) && s.StartsWith(findstr, StringComparison.OrdinalIgnoreCase);
var personList = people.Where(p => filter(p.FistName) || filter(p.LastName) || p.GetEmails().Select(e => e.Value).Any(filter));
Now if you want you can do that in parallel: 现在,如果您愿意,可以并行进行:
var personList = people.AsParallel(). Where(p => filter(p.FistName) || filter(p.LastName) || p.GetEmails().Select(e => e.Value).Any(filter));
You can use: 您可以使用:
Any()
instead of ToList().Count > 0
Any()
代替ToList().Count > 0
First()
and then check if it matches the condition instead of IndexOf (findstr, StringComparison.OrdinalIgnoreCase) == 0
First()
,然后检查它是否符合条件而不是IndexOf (findstr, StringComparison.OrdinalIgnoreCase) == 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.