none
Compareinfo.lastindexof problem with ignoresymbols and symbol RRS feed

  • Question

  • Whenever "IgnoreSymbols" is looking for ":" the return is = 5. Why? The correct value is -1.

    // OK. Returns 3.
    int Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAA:AA", ":", System.Globalization.CompareOptions.IgnoreCase);

    // OK. Returns 3.
    Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAA:AA", ":", System.Globalization.CompareOptions.IgnoreNonSpace);

    // BAD. Returns 5.
    Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAA:AA", ":", System.Globalization.CompareOptions.IgnoreSymbols);

    // OK. Returns 3.
    Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAABAA", "B", System.Globalization.CompareOptions.IgnoreSymbols);

    // OK. Returns 3.
    Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAA:AA", ":", System.Globalization.CompareOptions.IgnoreCase | System.Globalization.CompareOptions.IgnoreNonSpace);

    // BAD. Returns 5.
    Pos = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.LastIndexOf("AAA:AA", ":", System.Globalization.CompareOptions.IgnoreCase | System.Globalization.CompareOptions.IgnoreNonSpace | System.Globalization.CompareOptions.IgnoreSymbols);
    Friday, September 20, 2019 8:54 AM

Answers

  • That is correct. Refer to the Note to Callers section for the method documentation. It explicitly states that if you do a culture sensitive comparison (which happens if you don't include CompareOptions.Ordinal) then if the search string contains only ignorable characters (symbols in your case) then the method always returns the length of the string - 1. Since your inputs are 6 in length you get back 5. 

    To resolve this you should either do a culture insensitive search or ensure you are not searching for only ignorable characters.

    class Program
    {
        static void Main ( string[] args )
        {
            var tests = new[]
            {
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreNonSpace, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreSymbols, Expected = -1 }, //This is wrong
                new { Input = "AAABAA", Search = "B", Options = CompareOptions.IgnoreSymbols, Expected = 3 }, 
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols, Expected = -1 }, //This is wrong
    
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.Ordinal, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols, Expected = 5 },
            };
    
            foreach (var test in tests)
            {
                var actual = CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(test.Input, test.Search, test.Options);
                if (actual != test.Expected)
                    Console.WriteLine($"Expected {test.Expected} but found {actual} - Input = '{test.Input}', Search = '{test.Search}', Options = {test.Options}");
            };
        }
    }


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by zequion1 Friday, September 20, 2019 2:49 PM
    Friday, September 20, 2019 2:43 PM
    Moderator

All replies

  • That is correct. Refer to the Note to Callers section for the method documentation. It explicitly states that if you do a culture sensitive comparison (which happens if you don't include CompareOptions.Ordinal) then if the search string contains only ignorable characters (symbols in your case) then the method always returns the length of the string - 1. Since your inputs are 6 in length you get back 5. 

    To resolve this you should either do a culture insensitive search or ensure you are not searching for only ignorable characters.

    class Program
    {
        static void Main ( string[] args )
        {
            var tests = new[]
            {
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreNonSpace, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreSymbols, Expected = -1 }, //This is wrong
                new { Input = "AAABAA", Search = "B", Options = CompareOptions.IgnoreSymbols, Expected = 3 }, 
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols, Expected = -1 }, //This is wrong
    
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.Ordinal, Expected = 3 },
                new { Input = "AAA:AA", Search = ":", Options = CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols, Expected = 5 },
            };
    
            foreach (var test in tests)
            {
                var actual = CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(test.Input, test.Search, test.Options);
                if (actual != test.Expected)
                    Console.WriteLine($"Expected {test.Expected} but found {actual} - Input = '{test.Input}', Search = '{test.Search}', Options = {test.Options}");
            };
        }
    }


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by zequion1 Friday, September 20, 2019 2:49 PM
    Friday, September 20, 2019 2:43 PM
    Moderator
  • Thank you. I also have the problem that you have tried to enter values in the count parameter and always return -1 with indexof / lastindexof
    Friday, September 20, 2019 2:49 PM