Перевірте, чи містить список елемент, що містить рядок, і отримайте цей елемент


146

Під час пошуку відповіді на це запитання я зіткнувся з подібними, використовуючи LINQ, але мені не вдалося повністю зрозуміти їх (і, таким чином, реалізувати їх), оскільки я не знайомий з цим. Що я хотів би, в основному, це:

  1. Перевірте, чи містить якийсь елемент списку певний рядок.
  2. Якщо це так, знайдіть цей елемент.

Я, чесно кажучи, не знаю, як би я пішов робити це. Що я можу придумати, це це (звичайно, не працює):

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

Я знаю, Чому це не працює:

  • myList.Contains()не повертається true, оскільки він перевірить, чи відповідає цілий елемент списку рядку, який я вказав.
  • myList.IndexOf() не знайде події, оскільки, як це повторюється, він перевірить, чи відповідає елемент, що відповідає рядку.

Досі я не маю поняття, як вирішити цю проблему, але я думаю, що мені доведеться використовувати LINQ, як було запропоновано у подібних моїх питаннях. Якщо говорити, якщо це так, я хотів би, щоб відповідач пояснив мені використання LINQ у своєму прикладі (як я вже сказав, я не турбувався з цим у свій час із C #). Дякую заздалегідь, хлопці (та дівчата?).

EDIT: я придумав рішення; просто переведіть список, перевірте, чи містить поточний елемент рядок, а потім встановіть рядок, рівний поточному елементу. Мені цікаво, проте чи існує більш ефективний спосіб, ніж цей?

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

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}

як я згадую у своїй відповіді, старі петлі моди (як у вас є питання) майже завжди найшвидші. Але ти можеш це перевірити, якщо тебе не вистачає.
Маккей

У вашому списку може бути кілька рядків, що містять ваш рядок myString, в поточному циклі ви отримаєте останній елемент. Це залежить від вас, чи хочете ви знайти перше чи останнє, якщо ви просто хочете знайти перше, а потім розірвіть цикл після пошуку елемента.
Хабіб

Відповіді:


193

Тут ви маєте можливість використовувати Linq:

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

Якщо ви просто хочете повернути перший збіг:

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

if(match != null)
    //Do stuff

+1 - Або замінити Whereз FirstOrDefaultвашим другим випадкомmyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Хабіб

Чудова відповідь. Хоча просто з цікавості: чому це matchingвизначається компілятором ( var)? Оскільки я знаю, що мій список має тип String, чи було б його безпечно використовувати string matchingв цьому випадку?
Димитріс Іліадіс

1
@JimIliadis "var" і "string" означають абсолютно одне і те саме в цьому випадку - компілятор досить розумний, щоб знати, що результатом може бути лише "рядок". var - це дійсно лише річ у стилі кодування (коли не використовуються анонімні типи)
Дейв Біш,

коментуючи занадто стару тему, але знайшов один виняток із цього. коли ви використовуєте firstordefault (), переконайтеся, що він також може повернути значення за замовчуванням. тож, припустимо, ви передаєте рядок emy, тобто mystring = "", і ви нічого не очікуєте, але все-таки він відобразить перший елемент списку, оскільки ви вибрали firstordefault.
брудний розробник

@DirtyDeveloper Не впевнений, що ви маєте на увазі під цим - ваш приклад поверне 'null, якби в списку цілі не було порожніх рядків. Ви маєте рацію, якщо ви намагаєтесь використовувати FirstOrDefault () для типу структури, наприклад, Список <int> - FirstOrDefault () поверне "0", а не нульовий - однак питання стосувалося конкретно рядків
Дейв Біш

29

Основна відповідь: вам потрібно повторити цикл і перевірити, чи будь-який елемент містить вказаний рядок. Скажімо, код такий:

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

Еквівалентний, але короткий код:

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

Тут x - параметр, який діє як "елемент" у наведеному вище коді.


12
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}

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;
    }
}

Старі модні петлі майже завжди найшвидші.


Оскільки я берусь за ефективність, ти припускаєш, що цей метод швидший (таким чином, більш ефективний)?
Димитріс Іліадіс

2
Я не перевіряв це, але думаю, що це буде швидше. Лише коли-небудь потрібен один прохід через список, поки він щось не знайде і не вирветься рано (як, наприклад, параметри Linq можна зробити, якщо написано добре), не має виклику методу виклику linq, ані лямбда-накладні linq. Не те, що це величезні причини, що викликають занепокоєння, але можуть спричинити певний хіт на продуктивність.
Маккей

Чому не використовувати List.Equals ()?
F8ER

@ V.7 Тому що він хоче знати лише, чи містить один елемент у списку підрядку. list.equals не є правильним інструментом для завдання ["abc", "def", "ghi"] містить "привіт" так, як це описує ОП. list.equals навіть не приймає правильних типів даних.
Маккей

6

Якщо ви хочете список рядків, що містять ваш рядок:

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

Інший варіант - використовувати Linq FirstOrDefault

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

Майте на увазі, що Containsметод чутливий до регістру.


1
Добре нагадування про залежність від регістру, введіть StringComppare.InvariantCultureIgnoreCase
JoshYates1980

2

Ви можете використовувати FirstOrDefaultметод розширення Linq :

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

Це поверне елемент кулака, який містить підрядку myString, або nullякщо такого елемента не буде знайдено.

Якщо все, що вам потрібно, це індекс, використовуйте метод List<T>класу FindIndex:

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

Це поверне індекс елемента кулака, який містить підрядку myString, або -1якщо такого елемента не знайдено.


2

Тут є багато хороших відповідей, але я використовую простий, використовуючи Exists , як нижче:

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);
}

2

Ви повинні мати можливість використовувати щось подібне, для мене це нормально спрацювало:

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

або щось подібне, якщо вам потрібно подивитися, де це не відповідає.

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

1

ви можете використовувати

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

LINQ надає вам можливості "запитувати" будь-який збір даних. Ви можете використовувати синтаксис, як запит до бази даних (виберіть, де тощо) для колекції (тут колекція (список) рядків).

тож ти робиш на кшталт "дістань мені елементи зі списку, де це відповідає заданій умові"

всередині місця, де ви використовуєте "лямбда-вираз"

коротко сказати лямбда-вираз - це щось на кшталт (вхідний параметр => значення повернення)

тому для параметра "item" він повертає "item.Contains (" обов'язковий рядок ")". Таким чином, він повертає true, якщо елемент містить рядок і тим самим його вибирають зі списку, оскільки він задовольнив умову.


1

Щоб це було просто, використовуйте це;

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.
 }
}

Крім того, щоб зробити це за допомогою циклу, використовуйте це;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }

Просто для зазначення, ви пропустили кінцеву дужку з одного з рядків коду .. якщо (item.Contains ("Термін пошуку"))
Alex Alex

0

Я не бачив варіант bool в інших відповідях, тож сподіваюся, що нижче код комусь допоможе.

Просто використовуйте Any()

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

0

Можна комбінувати Any, Where, First та FirstOrDefault; або просто помістіть присудок у будь-який із цих методів залежно від необхідності.

Ймовірно, ви повинні уникати використання First, якщо ви не хочете, щоб виняток було кинуто, коли не знайдено відповідності. FirstOrDefault - це, як правило, кращий варіант, якщо ви знаєте, що він поверне типовий тип, якщо не знайдено відповідності (за замовчуванням string є null, int - 0, bool false, тощо).

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" }

Перевірте цей код @ https://rextester.com/TXDL57489

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.