2013-10-24 58 views
-1

我正在做一个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; 
    } 

正如你所看到的,我已经做了很多的私有方法,将检查搜索字符串与对象的字符串/日期/不管。 它一切正常。

但有没有更好/更快的方式来搜索一个单一的字符串的对象列表?

编辑

的方法InputStartWithSearchIsStringDate是私有方法,我在那里检查,如果输入的字符串与项目的数据开始。因此,如果CreatedBy是“Matthi Smith Junior”,并且我搜索了“Matthi Junior”,“Matthi Smith”,“Smith Junior”等,它会添加它。

IsStringDate正在检查搜索字符串是否等于日期时间格式。所以它包含一系列格式,并检查搜索字符串是否为该格式。

+3

请您谈一下“快” - 此刻,你确实有性能问题呢?我首先关注*简单*代码。 –

+1

另外,InputStartWithSearch和DateToString是做什么的? “searchProjects”从哪里来?为什么你的foreach循环中有一个return语句?这对我来说看起来很不对劲。我会专注于首先获得清晰和正确的代码。 –

+0

现在还不行,因为我只使用了大约30个虚拟对象,但是当它连接到它们的数据库时,它将会是1000多个对象。所以它正在工作,但如果有人能够找到一种方法来加快速度,那么现在就应该改变它,而不是在启动和运行时。 – Moelbeck

回答

2

你需要的是一个重载的方法:只要

if (InputStartWithSearch(searchString, proj.ProjectName, proj.Country, proj.CreateDate)) 
{ 
    searchProjects.Add(proj); 
} 

您可以字符串列表来检查你:

bool InputStartWithSearch(string search, params string[] inputs) 
{ 
    return inputs.Any(i => InputStartWithSearch(i, string)); 
} 

然后你可以使用它像这样喜欢。

可能是一个好主意,可以颠倒原始方法中的参数顺序,以减少混淆。

要直接使用LINQ获得匹配的项目清单,你可以这样做:

var matchingProjects = _projects.Where(i => InputStartWithSearch(searchString, i.ProjectName, i.Country, i.CreateDate)); 
+2

这是否使它更快,或者它只是使它“更漂亮”和简单? 我其实很喜欢你的解决方案,没想过这个。 – Moelbeck

+0

它从根本上不会更快 - 它仍然在进行串行搜索来查找匹配项。但可读性和代码清晰度本身提供了真正的价值。正如Jon Skeet在他的评论中暗示的那样,这可能不会成为代码中的瓶颈 - 因此保持清晰度最有可能胜过此处的优化。 – Baldrick

0

您可以轻松修改代码并使用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"]; 

很明显,将“projectName”更改为所需的值。

编辑

基础上开始你可以做(​​未测试的代码)

Project projectDetails = myProjects.Where (m => m.Key.Contains ("projectName").Select (m => m.Value); 
+0

它看起来像搜索是“开始”的,这将不适用于字典。 –

0

首先,你可以重构searchProjects.Contains()检查到一个后卫在声明的顶部循环。这将简化事情。然后,您可以将每个项目的属性连接到具有唯一分隔符的单个字符串中。然后搜索更容易。这并不比你现有的方法更快,它只是更短。

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; 
} 

只要'|'字符不会出现在任何字段中...

0

您可以使用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(); 
} 
+0

我没有使用标准的string.StartWith()。我不得不拆分字符串,并检查substring是否以它开头。因此,如果ProjectName是“项目编号10”,并且我搜索了“项目10”,“编号10”或“项目”,它应该将其添加到列表中。所以我做了我自己的检查。 – Moelbeck

+0

确定改变它使用InputStartWithSearch –

相关问题