c# - Búsqueda de lista insensible a mayúsculas y minúsculas
search case-insensitive (6)
Basado en la respuesta anterior de Adam Sills, aquí hay un buen método de extensiones limpias para Contiene ... :)
///----------------------------------------------------------------------
/// <summary>
/// Determines whether the specified list contains the matching string value
/// </summary>
/// <param name="list">The list.</param>
/// <param name="value">The value to match.</param>
/// <param name="ignoreCase">if set to <c>true</c> the case is ignored.</param>
/// <returns>
/// <c>true</c> if the specified list contais the matching string; otherwise, <c>false</c>.
/// </returns>
///----------------------------------------------------------------------
public static bool Contains(this List<string> list, string value, bool ignoreCase = false)
{
return ignoreCase ?
list.Any(s => s.Equals(value, StringComparison.OrdinalIgnoreCase)) :
list.Contains(value);
}
Tengo una lista de testList
que contiene un montón de cadenas. Me gustaría agregar una nueva cadena en testList
solo si aún no existe en la lista. Por lo tanto, necesito hacer una búsqueda insensible a mayúsculas y minúsculas de la lista y hacerla eficiente. No puedo usar Contains
porque eso no tiene en cuenta la carcasa. Tampoco quiero usar ToUpper/ToLower
por razones de rendimiento. Me encontré con este método, que funciona:
if(testList.FindAll(x => x.IndexOf(keyword,
StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
Console.WriteLine("Found in list");
Esto funciona, pero también coincide con palabras parciales. Si la lista contiene "cabra", no puedo agregar "avena" porque dice que "avena" ya está en la lista. ¿Hay alguna manera de buscar de manera eficiente las listas de una manera que no distinga entre mayúsculas y minúsculas, donde las palabras tienen que coincidir exactamente? Gracias
En lugar de String.IndexOf, use String.Equals para asegurarse de no tener coincidencias parciales. Además, no use FindAll ya que eso pasa por cada elemento, use FindIndex (se detiene en el primero que golpea).
if(testList.FindIndex(x => x.Equals(keyword,
StringComparison.OrdinalIgnoreCase) ) != -1)
Console.WriteLine("Found in list");
Alternativamente, utilice algunos métodos LINQ (que también se detiene en el primero que golpea)
if( testList.Any( s => s.Equals(keyword, StringComparison.OrdinalIgnoreCase) ) )
Console.WriteLine("found in list");
Está comprobando si el resultado de IndexOf es mayor o igual a 0, es decir, si la coincidencia comienza en cualquier parte de la cadena. Intente comprobar si es igual a 0:
if (testList.FindAll(x => x.IndexOf(keyword,
StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
Console.WriteLine("Found in list");
Ahora "cabra" y "avena" no coincidirán, pero "cabra" y "goa" lo harán. Para evitar esto, puede comparar las longitudes de las dos cadenas.
Para evitar toda esta complicación, puede usar un diccionario en lugar de una lista. La clave sería la cadena en minúscula, y el valor sería la cadena real. De esta forma, el rendimiento no se ve afectado porque no tiene que usar ToLower
para cada comparación, pero aún puede usar Contains
.
Me doy cuenta de que esta es una publicación anterior, pero por si acaso alguien más está buscando, puede usar Contains
al proporcionar el comparador de igualdad de cadenas insensible a mayúsculas y minúsculas de esta manera:
if (testList.Contains(keyword, StringComparer.OrdinalIgnoreCase))
{
Console.WriteLine("Keyword Exists");
}
Esto ha estado disponible desde .net 2.0 según msdn .
Según la respuesta de Lance Larsen, aquí hay un método de extensión con la cadena recomendada. Compare en lugar de string.Equals
Se recomienda encarecidamente que utilice una sobrecarga de String.Compare que tome un parámetro StringComparison. Estas sobrecargas no solo le permiten definir el comportamiento de comparación exacto que pretendía, su uso también hará que su código sea más legible para otros desarrolladores. [ Josh Free @ BCL Team Blog ]
public static bool Contains(this List<string> source, string toCheck, StringComparison comp)
{
return
source != null &&
!string.IsNullOrEmpty(toCheck) &&
source.Any(x => string.Compare(x, toCheck, comp) == 0);
}
Tuve un problema similar, necesitaba el índice del artículo pero tenía que ser insensible a las mayúsculas y minúsculas, busqué en la web durante unos minutos y no encontré nada, así que simplemente escribí un pequeño método para hacerlo, esto es lo que hizo:
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());
}
Agregue este código al mismo archivo y llámelo así:
int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);
Espero que esto ayude, buena suerte!