How to add a case-insensitive option to Array.IndexOf
Asked Answered
P

7

33

I have a string:

string str = "hello";

And an array:

string[] myarr = new string[] {"good", "Hello", "this", "new"};

I need to get the index of ("Hello") from the array when comparing with my string ("hello") (without using a loop).

I have tried:

int index = Array.IndexOf(myarr, str);

This returns -1, because of the capital "H", but I want a result of 1.

I have even tried with StringComparer.OrdinalIgnoreCase but no avail.

Pretence answered 20/1, 2012 at 0:3 Comment(0)
P
9

Since you are looking for index. Try this way.

Array.FindIndex(myarr, t => t.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) >=0);
Perceptive answered 20/1, 2012 at 17:30 Comment(1)
Note that this answer searches for a substring of the reference string in each element of the input array enumerated by Array.FindIndex(), due to using System.String.IndexOf(). To match the elements in full, use the analogousSystem.String.Equals() overload, as shown in the other answers.Kippie
R
59

Beaware!!
The answer marked as a solution might have some problem, like with:

string array[] = {"hello", "hi", "bye" , "welcome" , "hell"}

If you use the same method (as described in the answer) to find the index of word "hell":

int indexOfArray = Array.FindIndex(array, t => t.IndexOf("hell", StringComparison.InvariantCultureIgnoreCase) >= 0);

you will get the result indexOfArray = 0 instead of 4.

Instead use:

Array.FindIndex(array, t => t.Equals("hell", StringComparison.InvariantCultureIgnoreCase));

to get a proper result.

Rhiana answered 9/1, 2014 at 11:51 Comment(1)
why InvariantCultureIgnoreCase instead of OrdinalIgnoreCase ?Theory
P
9

Since you are looking for index. Try this way.

Array.FindIndex(myarr, t => t.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) >=0);
Perceptive answered 20/1, 2012 at 17:30 Comment(1)
Note that this answer searches for a substring of the reference string in each element of the input array enumerated by Array.FindIndex(), due to using System.String.IndexOf(). To match the elements in full, use the analogousSystem.String.Equals() overload, as shown in the other answers.Kippie
H
6

Array.IndexOf calls the default "Equals" method which is case-sensitive. Try this:

Array.FindIndex(myarr, t => t.Equals(str, StringComparison.InvariantCultureIgnoreCase))
Hypno answered 20/1, 2012 at 0:13 Comment(0)
O
3
var result = myarr.FindIndex(s => s.Equals(str, StringComparison.OrdinalIgnoreCase));
Orogeny answered 20/1, 2012 at 0:11 Comment(0)
P
3

1) if you want to search only once and want to keep source array, you can use this:

        public static void example1()
        {
            string[] myarr = { "good", "Hello", "this", "new" };
            var str = "new";
            var res= Array.FindIndex(myarr, x=>string.Equals(x, str, StringComparison.InvariantCultureIgnoreCase));
        }

2) if you will search many times it will be better to use this:

public static void example1()
    {
        string[] myarr = {"good", "Hello", "this", "new"};
        var str = "new";
        var res = Array.IndexOf(Array.ConvertAll(myarr, ToStringlowerCase), str.ToLowerInvariant());
    }

3) the answer above is incorrect :

string array[] = {"hello", "hi", "bye" , "welcome" , "hell"}
Int Indexofary = Array.FindIndex(array, t => t.IndexOf("hell", StringComparison.InvariantCultureIgnoreCase) >=0);

will not work at all, because it searches not the string, but substring.

Algorithm iterates words in array, when 1st word "hello" taken, algorithm tries to find index of 'hell' and this index is 1. 1 is > then 0 and algorithm will be finished without going to other words.

If you don't want to search substrings but want to search strings, algorythm should be fixed. This algorithm can be fixed by adding check that substring starts from 1st char t.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) == 0 and the length of the words equals str.Length == t.Length. Fixed:

        public static int example3()
    {
        string[] myarr = { "hHello", "hi", "bye", "welcome", "hell" };
        var str = "hell";
        return Array.FindIndex(myarr, t => t.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) == 0 && str.Length == t.Length);
    }
Paction answered 9/9, 2016 at 10:1 Comment(0)
B
0

Since Array.IndexOf is generic, it makes sense to make a generic extension function:

public static int IndexOf<T>(this T[] source, T value)
{
  return IndexOf<T>(source, value, StringComparison.InvariantCultureIgnoreCase);
}

public static int IndexOf<T>(this T[] source, T value, StringComparison stringComparison)
{
  if (typeof(T) == typeof(string))
    return Array.FindIndex(source, m => m.ToString().Equals(value.ToString(), stringComparison));
  else
    return Array.IndexOf(source, value);
}
Bisayas answered 16/1, 2017 at 17:33 Comment(1)
This does not make sense, as StringComparison only applies to string arrays and thus only adding an extension method for this string[] source ensures you don't pollute other generic types with this overload.Sugarplum
Q
-1

I had a similar problem, I needed the index of the item but it had to be case insensitive, i looked around the web for a few minutes and found nothing, so I just wrote a small method to get it done, here is what I did:

private static int getCaseInvariantIndex(List<string> ItemsList, string searchItem)
{
    List<string> lowercaselist = new List<string>();

    foreach (string item in ItemsList)
    {
        lowercaselist.Add(item.ToLower());
    }

    return lowercaselist.IndexOf(searchItem.ToLower());
}

Add this code to the same file, and call it like this:

int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);

Hope this helps, good luck!

Quincey answered 28/1, 2013 at 17:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.