按单个字符串搜索对象最快的列表
本文关键字:列表 对象 单个 字符串 搜索 | 更新日期: 2023-09-27 18:36:37
我正在做一个Web应用程序,其中我有一个文本框用于搜索对象列表。
对象是这样的:
public class Project : IDbProject
{
public string ProjectName { get; set; }
public string Country { get; set; }
public string Customer { get; set; }
public DateTime UploadDate { get; set; }
public DateTime CreateDate { get; set; }
public string CreatedBy { get; set; }
}
,并且列表是一个IList<IProject>
。我的搜索/过滤正在通过列表,并与对象中的每个字符串进行比较,例如:
public IList<IProject> GetSearchedProjects(string searchString)
{
foreach (var proj in _projects)
{
if (InputStartWithSearch(proj.ProjectName, searchString) && !searchProjects.Contains(proj))
{
searchProjects.Add(proj);
continue;
}
if (InputStartWithSearch(proj.Country, searchString) && !searchProjects.Contains(proj))
{
searchProjects.Add(proj);
continue;
}
if (InputStartWithSearch(proj.CreatedBy, searchString) && !searchProjects.Contains(proj))
{
searchProjects.Add(proj);
continue;
}
if (InputStartWithSearch(proj.ProjectState, searchString) && !searchProjects.Contains(proj))
{
searchProjects.Add(proj);
continue;
}
if (IsStringDate(searchString))
if (IsDatesEqual(proj.CreateDate, searchString) && !searchProjects.Contains(proj))
{
searchProjects.Add(proj);
}
}
return searchProjects;
}
return _projects;
}
如您所见,我制作了很多私有方法,这些方法将使用对象的字符串/日期/任何内容检查搜索字符串。这一切都很好。
但是有没有更好/更快的方法来按单个字符串在对象列表中搜索?
编辑
方法InputStartWithSearch
和IsStringDate
是私有方法,我在其中检查输入字符串是否以项目数据开头。因此,如果 CreatedBy 是"Matthi Smith Junior",而我搜索了"Matthi Junior"、"Matthi Smith"、"Smith Junior"等,它就会添加它。
IsStringDate 正在检查搜索字符串是否等于日期时间格式。因此,它包含一系列格式,并检查搜索字符串是否为该格式。
的是一个重载的方法:
bool InputStartWithSearch(string search, params string[] inputs)
{
return inputs.Any(i => InputStartWithSearch(i, string));
}
然后你可以像这样使用它:
if (InputStartWithSearch(searchString, proj.ProjectName, proj.Country, proj.CreateDate))
{
searchProjects.Add(proj);
}
您可以根据需要制作要检查的字符串列表。
颠倒原始方法中参数的顺序可能是一个好主意,以使事情也变得不那么混乱。
若要直接使用 LINQ 获取匹配项目的列表,可以执行以下操作:
var matchingProjects = _projects.Where(i => InputStartWithSearch(searchString, i.ProjectName, i.Country, i.CreateDate));
您可以稍微更改代码并使用 Dictionary 对象,其中键是项目名称,值是对象。 然后,您的班级将变为:
public class Project : IDbProject
{
public string Country { get; set; }
public string Customer { get; set; }
public DateTime UploadDate { get; set; }
public DateTime CreateDate { get; set; }
public string CreatedBy { get; set; }
}
然后,您将创建一个新的字典对象
Dictionary <string, Project> myProjects = new Dictionary<string, Project>();
然后,您将填充它,将字符串设置为项目名称,当您想要引用它时,请执行以下操作:
Project projectDetails = myProjects["projectName"];
显然,将"项目名称"更改为您需要的名称。
编辑
基于您可以做的开始(代码未经测试)
Project projectDetails = myProjects.Where (m => m.Key.Contains ("projectName").Select (m => m.Value);
你可以重构 searchProjects.Contains() 签入到循环顶部的 guard 语句中。这会简化事情。然后,可以将每个项目的属性连接到具有唯一分隔符的单个字符串中。然后搜索更容易。这并不比您现有的方法快,只是更短。
public IList<IProject> GetSearchedProjects(string searchString)
{
foreach (var proj in _projects)
{
if (!searchProjects.Contains(proj))
continue;
StringBuilder sb = new StringBuilder();
sb.Append("|").Append(proj.ProjectName);
sb.Append("|").Append(proj.Country);
sb.Append("|").Append(proj.CreatedBy);
sb.Append("|").Append(proj.UploadDate.ToString());
if (sb.ToString().Contains("|" + searchString))
searchProjects.Add(proj);
}
return searchProjects;
}
只要"|"字符不出现在任何字段中...
你可以使用 linq。同样,它不是更快,但代码更简单。
public IList<IProject> GetSearchedProjects(string searchString)
{
return (from p in _projects
where searchProjects.Contains(p) &&
(InputStartWithSearch(p.ProjectName, searchString) ||
InputStartWithSearch(p.Country, searchString) ||
InputStartWithSearch(p.CreatedBy, searchString) ||
DateToString(p.CreateDate).Contains(searchString.ToLower()))
select p).ToList();
}