LINQ按匹配字符位置排序

时间:2012-07-15 05:52:18

标签: c# linq list

我正在实施“搜索”自动填充功能。我想返回一个按用户提交的字符排序排序的结果列表,其中排序结果顶部的项目是字符串中包含第一个到第n个字符的字符的项目。

使用LINQ有一种优雅的方法吗?

例如,假设当用户键入“un”时,将从数据库中返回以下项目。

  • 美国德克萨斯州
  • 佛罗里达州,美国
  • 纽约,美国
  • 美国

我想按如下方式返回显示的有序结果:

  1. 美国
  2. 美国德克萨斯州
  3. 佛罗里达州,美国
  4. 纽约,美国
  5. 请注意,对于“un”以上的每个字符串,位于1-2,7-8,10-11和11-12位置。

4 个答案:

答案 0 :(得分:2)

一般来说@HugoRune的答案都有效,但有两个问题的效率有点低。

  1. 使用ToLower()会导致所有字符串首先转换为小写,即使firts char的比较显示它们不匹配。

  2. 我们两次进行基本相同的比较。一次使用Contains(),一次使用IndexOf()。所以我们经历了两次字符串。

  3. 以下代码的效率至少是其两倍:

            IEnumerable<string> stateNames= [your source here];
            string searchString="un";
    
            var result = 
                stateNames
                    .Select(state=> new {Name=state, Index = state.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase)})
                    .Where(tuple=>tuple.Index>=0)
                    .OrderBy(tuple=>tuple.Index)
                    .Select(tuple=>tuple.Name);
    

答案 1 :(得分:1)

您可以使用IndexOf获取子字符串的位置,并且可以在OrderBy子句中使用该索引

(以下假设您有一个db表“States”,其中包含“Name”列)

var result = dc.States
             .Where(s=>s.Name.ToLower().Contains("un"))
             .OrderBy(s=>s.Name.ToLower().IndexOf("un"));

或简单的缓存解决方案,如果您不想每次都访问数据库:

// call this once during initialisation
List<States> cachedStates = 
    dc.States.ToList();

...

// call this every time
var result = cachedStates
             .Where(s=>s.Name.ToLower().Contains("un"))
             .OrderBy(s=>s.Name.ToLower().IndexOf("un"));

答案 2 :(得分:0)

我对实现自动完成功能的建议是在应用程序加载和缓存时按名称按升序排列所有国家/地区名称及其ID。现在,无论何时用户键入,都应使用此缓存结果集进行匹配,使用linq查询。获得更好性能的另一个调整是拥有最小字符,例如: 2在你的情况下然后只做linq查询

实现这种方式的原因:您只需访问数据库一次,即可获取所有国家/地区名称,而不是每个字符的密钥。请注意,国家/地区的更改并非每天都在进行,因此您的缓存只能在应用程序重新启动时过期。

希望这有帮助

答案 3 :(得分:0)

使用CompareTo方法,如下所示:

SomeContext.ACollection.Where(...).OrderBy(x=> searchTerm.CompareTo(x) > 0)

CompareTo方法返回一个整数,表示比较字符串将按字符顺序排序的位置。