Compruebe si la lista contiene un elemento que contiene una cadena y obtenga ese elemento

146

Al buscar una respuesta a esta pregunta, me he encontrado con otras similares que utilizan LINQ, pero no he podido entenderlas completamente (y, por lo tanto, implementarlas), ya que no estoy familiarizado con ella. Lo que me gustaría, básicamente, es esto:

  1. Compruebe si algún elemento de una lista contiene una cadena específica.
  2. Si es así, obtén ese elemento.

Sinceramente, no sé cómo haría para hacer eso. Lo que se me ocurre es esto (no funciona, por supuesto):

if (myList.Contains(myString))
    string element = myList.ElementAt(myList.IndexOf(myString));

Sé POR QUÉ no funciona:

  • myList.Contains()no regresa true, ya que verificará si un elemento completo de la lista coincide con la cadena que especifiqué.
  • myList.IndexOf() no encontrará una ocurrencia, ya que, como es el caso nuevamente, verificará si hay un elemento que coincida con la cadena.

Aún así, no tengo idea de cómo resolver este problema, pero creo que tendré que usar LINQ como se sugiere en preguntas similares a las mías. Dicho esto, si ese es el caso aquí, me gustaría que el respondedor me explique el uso de LINQ en su ejemplo (como dije, no me he molestado en mi tiempo con C #). Gracias de antemano chicos (y chicas).

EDITAR: se me ocurrió una solución; simplemente recorra la lista, verifique si el elemento actual contiene la cadena y luego configure una cadena igual al elemento actual. Sin embargo, me pregunto, ¿hay una forma más eficiente que esta?

string myString = "bla";
string element = "";

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}
Dimitris Iliadis
fuente
Como mencioné en mi respuesta, los bucles antiguos (como tú tienes como pregunta) son casi siempre los más rápidos. Pero podrías probarlo si te importa lo suficiente.
McKay
Puede haber múltiples cadenas en su lista que contengan su cadena myString, en su ciclo actual, obtendrá el último elemento. Depende de usted si desea encontrar el primero o el último, si solo desea encontrar el primero, luego rompa el ciclo después de encontrar el artículo.
Habib

Respuestas:

193

Debería poder usar Linq aquí:

var matchingvalues = myList
    .Where(stringToCheck => stringToCheck.Contains(myString));

Si simplemente desea devolver el primer elemento coincidente:

var match = myList
    .FirstOrDefault(stringToCheck => stringToCheck.Contains(myString));

if(match != null)
    //Do stuff
Dave Bish
fuente
+1 - O reemplazar Wherecon FirstOrDefaulten su segundo casomyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Habib
Gran respuesta. Sin embargo, solo por curiosidad: ¿por qué está matchingdeterminado por el compilador ( var)? Como sé que mi lista es de tipo String, ¿sería seguro usarla string matchingen este caso?
Dimitris Iliadis
1
@JimIliadis "var" y "string" significan exactamente lo mismo en este caso: el compilador es lo suficientemente inteligente como para saber que el resultado solo puede ser 'string'. var es realmente solo un estilo de codificación (cuando no se utilizan tipos anónimos)
Dave Bish
comentando un hilo demasiado viejo, pero encontré una excepción al respecto. cuando use firstordefault () asegúrese de que también pueda devolver el valor predeterminado. entonces, supongamos que está pasando una cadena vacía, es decir, mystring = "" y no espera que se muestre nada, pero aún así mostrará el primer elemento de la lista porque ha seleccionado firstordefault.
Desarrollador sucio
@DirtyDeveloper No estoy seguro de qué quiere decir con esto: su ejemplo devolvería 'nulo, si no hubiera cadenas vacías en la lista de destino. Tiene razón si está intentando usar FirstOrDefault () en un tipo de estructura, por ejemplo, List <int> - FirstOrDefault () devolverá '0' y no será nulo; sin embargo, la pregunta fue específicamente sobre cadenas
Dave Bish
29

La respuesta básica es: necesita iterar a través del bucle y verificar que cualquier elemento contenga la cadena especificada. Entonces, digamos que el código es:

foreach(string item in myList)
{
    if(item.Contains(myString))
       return item;
}

El código equivalente, pero conciso, es:

mylist.Where(x => x.Contains(myString)).FirstOrDefault();

Aquí, x es un parámetro que actúa como "elemento" en el código anterior.

userda
fuente
12
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}
Chris
fuente
9
for (int i = 0; i < myList.Length; i++)
{
    if (myList[i].Contains(myString)) // (you use the word "contains". either equals or indexof might be appropriate)
    {
        return i;
    }
}

Los bucles antiguos son casi siempre los más rápidos.

McKay
fuente
Ya que voy por la eficiencia, ¿estás sugiriendo que este método es más rápido (por lo tanto, más eficiente)?
Dimitris Iliadis
2
No lo he probado, pero supongo que esto sería más rápido. Solo requiere una pasada a través de la lista, hasta que encuentre algo y salga temprano (como lo harían las opciones de Linq si se escriben bien), no tiene la sobrecarga de invocación del método de linq, o la sobrecarga lambda de linq tampoco. No es que esas sean grandes causas de preocupación, pero pueden causar cierto impacto en el rendimiento.
McKay
¿Por qué no usar List.Equals ()?
F8ER
@ V.7 Porque solo quiere saber si un elemento de la lista contiene una subcadena. list.equals no es la herramienta correcta para el trabajo ["abc", "def", "ghi"] contiene "hola" como lo describe el OP. list.equals ni siquiera toma los tipos de datos correctos.
McKay
6

Si desea una lista de cadenas que contiene su cadena:

var newList = myList.Where(x => x.Contains(myString)).ToList();

Otra opción es usar Linq FirstOrDefault

var element = myList.Where(x => x.Contains(myString)).FirstOrDefault();

Tenga en cuenta que el Containsmétodo distingue entre mayúsculas y minúsculas.

Alessandro D'Andria
fuente
1
Buen recordatorio sobre mayúsculas y minúsculas, implemente StringComparison.InvariantCultureIgnoreCase
JoshYates1980
2

Puede usar el FirstOrDefaultmétodo de extensión de Linq :

string element = myList.FirstOrDefault(s => s.Contains(myString));

Esto devolverá el primer elemento que contiene la subcadena myString, o nullsi no se encuentra dicho elemento.

Si todo lo que necesita es el índice, use el método de la List<T>clase FindIndex:

int index = myList.FindIndex(s => s.Contains(myString));

Esto devolverá el índice del primer elemento que contiene la subcadena myString, o -1si no se encuentra dicho elemento.

pswg
fuente
2

Muchas buenas respuestas aquí, pero uso una simple usando Exists , como se muestra a continuación:

foreach (var setting in FullList)
{
    if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName)) 
       setting.IsActive = true; // do you business logic here 
    else
       setting.IsActive = false;
    updateList.Add(setting);
}
Ali
fuente
2

Deberías poder usar algo como esto, me ha funcionado bien:

var valuesToMatch = yourList.Where(stringCheck => stringCheck.Contains(myString));

o algo como esto, si necesita mirar donde no coincide.

 var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));
Goku
fuente
1

puedes usar

var match=myList.Where(item=>item.Contains("Required String"));
foreach(var i in match)
{
//do something with the matched items
}

LINQ le proporciona capacidades para "consultar" cualquier recopilación de datos. Puede usar la sintaxis como una consulta de base de datos (seleccionar, dónde, etc.) en una colección (aquí la colección (lista) de cadenas).

así que estás haciendo como "conseguirme elementos de la lista donde satisface una condición dada"

dentro de donde está utilizando una "expresión lambda"

decir brevemente la expresión lambda es algo así como (parámetro de entrada => valor de retorno)

entonces para un parámetro "item", devuelve "item.Contains (" string requerido ")". Por lo tanto, devuelve verdadero si el elemento contiene la cadena y, por lo tanto, se selecciona de la lista ya que cumple la condición.

Nithin Nayagam
fuente
1

Para que sea simple, use esto;

foreach(string item in myList)//Iterate through each item.
{
 if(item.Contains("Search Term")//True if the item contains search pattern.
 {
   return item;//Return the matched item.
 }
}

Alternativamente, para hacer esto con for loop, use esto;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }
devavx
fuente
Solo para señalar, se perdió un soporte final de una de las líneas de código ... if (item.Contains ("Search Term"))
Alex
0

No he visto la opción bool en otras respuestas, así que espero que el siguiente código ayude a alguien.

Solo usa Any()

string myString = "test";
bool exists = myList
             .Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();
Pawel Czapski
fuente
0

Es posible combinar Any, Where, First y FirstOrDefault; o simplemente coloque el predicado en cualquiera de esos métodos dependiendo de lo que se necesite.

Probablemente debería evitar usar First a menos que desee que se lance una excepción cuando no se encuentre ninguna coincidencia. FirstOrDefault suele ser la mejor opción siempre que sepa que devolverá el valor predeterminado del tipo si no se encuentra una coincidencia (el valor predeterminado de la cadena es nulo, int es 0, bool es falso, etc.).

using System.Collections.Generic;
using System.Linq;


bool exists;
string firstMatch;
IEnumerable<string> matchingList;

var myList = new List<string>() { "foo", "bar", "foobar" };

exists = myList.Any(x => x.Contains("o"));
// exists => true

firstMatch = myList.FirstOrDefault(x => x.Contains("o"));
firstMatch = myList.First(x => x.Contains("o"));
// firstMatch => "foo"

firstMatch = myList.First(x => x.Contains("dark side"));
// throws exception because no element contains "dark side"

firstMatch = myList.FirstOrDefault(x => x.Contains("dark side"));
// firstMatch => null

matchingList = myList.Where(x => x.Contains("o")); 
// matchingList => { "foo", "foobar" }

Pruebe este código @ https://rextester.com/TXDL57489

deleb
fuente