Stian
Stian

Reputation: 1602

Case insensitive text search in C#: How can I keep the original case when highlighting matching phrases?

I have a case insensitive text search (in the controller, I'm doing .ToLower() on both sides of the comparison), and I am highlighting the search phrases in the result text like this:

@Html.Raw(searchPhrase.Length == 0 
    ? item.Description 
    : (item.Description ?? "") // An item's Description could be NULL
        .Replace(searchPhrase, $"<span class='highlight'>{searchPhrase}</span>"))

Items matching the search phrase are displayed, but if the case doesn't match, there won't be any highlighting.

I want matching text to be highlighted even if the case doesn't match, and I want to keep the original case.

E.g.: If I search for "Potato", both "Potato" and "potato" should be highlighted in the search result.

I have seen some similar questions around, but not for C#, and I have not been able to translate any of the solutions to C#.

Upvotes: 0

Views: 391

Answers (2)

John Lord
John Lord

Reputation: 2185

Well you can't do Replace like that because you are overwriting your source data.

You either need to mark the beginning and end of each match and, starting at the end of the string and going to the beginning, insert your opening and closing brackets, or write a custom replace routine. I threw together a rather basic version of the latter, but it works. It keeps the existing values so all cases will be preserved.

        string testData = "This is my fake data for matching this string";
        string searchPhrase = "thiS";
        string resultSet = "";
        for (int i = 0; i < testData.Length - searchPhrase.Length; i++)
        {
            if (searchPhrase.ToLower() == testData.Substring(i, searchPhrase.Length).ToLower())
            {
                resultSet += "<span class='highlight'>" + testData.Substring(i, searchPhrase.Length) + "</span>";
                i += searchPhrase.Length -1;
            }
            else
            {
                resultSet += testData[i].ToString();
            }
        }
        Console.WriteLine(resultSet);

Granted, this code could probably be made faster with string parsing but I'll leave all that to you if you want to redo it.

Upvotes: 2

NetMage
NetMage

Reputation: 26917

To elaborate on @stuartd 's comment, here is how to use Regex.Replace for the same thing:

var ans = searchPhrase.Length == 0
            ? (item.Description ?? String.Empty)
            : Regex.Replace((item.Description ?? String.Empty), // An item's Description could be NULL
                            Regex.Escape(searchPhrase),
                            "<span class='highlight'>$&</span>",
                            RegexOptions.IgnoreCase);

Upvotes: 1

Related Questions