Search code examples
c#.netlinqsortinggenerics

OrderBy search results that startswith searcch word then by results that contains search word


I have an object like this:

  public class MyObject
{
    public List<string> Names { get; set; }
    // other props
} 

and I have a filtered List like this :

   var freeText = "comm";
    var list = new List<MyObject>(); // Initialized

    var searchResult = list.Where(o =>
        o.Names.Any(n => n.ToLower().StartsWith(freeText.ToLower())) ||
        o.Names.Any(n => n.ToLower().Contains(freeText.ToLower())));

and it's working fine but, what I'm trying to do is to get the search results ordered by starts with first then by contains.

ex:

Obj 1 {Names : [ "free communication" ,"some name"]},
Obj 2 { Names : ["communcation Center", "whatever"]}

I want the result to be [Obj2, Obj1].

I tried to orderBy index of freeText but it doesn't seem to work on an array/list of string. I tried to ulter the solution at This question so it works on array instead of string but it didn't work. any idea how to to this?


Solution

  • You can implement a simple scoring mechanism where you'll capture two flags (startsWith and contains) and use those flags both for filtering and for sorting:

    var result = list.Select(item => new
    {
        item,
        startsWith = item.Names.Any(n => n.ToLower().StartsWith(freeText.ToLower())),
        contains = item.Names.Any(n => n.ToLower().Contains(freeText.ToLower())),
    })
    .Where(item => item.startsWith || item.contains)
    .OrderByDescending(item => item.startsWith)
    .ThenByDescending(item => item.contains)
    .Select(x => x.item);