Перевірте, чи містить список <t> якийсь інший список


97

У мене є такий список параметрів:

public class parameter
{
    public string name {get; set;}
    public string paramtype {get; set;}
    public string source {get; set;}
}

IEnumerable<Parameter> parameters;

І масив рядків, який я хочу перевірити.

string[] myStrings = new string[] { "one", "two"};

Я хочу переглядати список параметрів і перевіряти, чи властивість джерела дорівнює будь-якому з масиву myStrings. Я можу зробити це за допомогою вкладених foreach, але я хотів би навчитися робити це більш приємним чином, оскільки я бавився з linq і подобався методам розширення на незліченні, наприклад, де тощо, тому вкладені foreachs просто почуваються неправильно. Чи існує більш елегантний бажаний спосіб linq / lambda / delegete для цього.

Дякую

Відповіді:


207

Ви можете використовувати вкладений Any()для цієї перевірки, який доступний на будь-якому Enumerable:

bool hasMatch = myStrings.Any(x => parameters.Any(y => y.source == x));

Швидше виступати на великих колекцій буде проект parametersдля , sourceа потім використовувати , Intersectякий внутрішньо використовує HashSet<T>так замість O (N ^ 2) для першого підходу (еквівалент двох вкладених циклів) , ви можете зробити перевірку в O (N):

bool hasMatch = parameters.Select(x => x.source)
                          .Intersect(myStrings)
                          .Any(); 

Крім того, як побічний коментар ви повинні використовувати великі імена класів та назви властивостей, щоб відповідати вимогам стилю C #.


дякую, здається, це те, що я шукаю, я спробую це. Потрібно трохи більше пограти з функціональною стороною справи. що стосується використання великих класів та властивостей, то я просто забув, коли писав приклад вище.
gdp

1
Чому O (n ^ 2)? Чи не O (n * m), коли мова йде про дві змінні, а не про одну? Оскільки m (параметри) є константою, це те саме, що O (n). Я не розумію, як перетин тут повинен бути набагато швидшим? Але погодьтеся, Intersect може бути швидшим, але не гарантовано.
Squazz

Ви маєте рацію, що це має бути O (n * m) - m, однак, не є константою - це розмір одного зі списків, хоча в наведеному конкретному прикладі це може бути "2". Навіть постійні значення, хоча і не є незначними на практиці - для всіх нетривіальних довжин списків це Intersectбуде швидше - якщо списки тривіально короткі, це так чи інакше не має значення (в такому випадку продуктивність, мабуть, зовсім не ваша проблема )
BrokenGlass

як ви можете зрозуміти індекс списку, де умова стає істинною? У мене є список із реченнями. У мене є масив із певними словами. Мені потрібні індекси списку, якщо в реченні є щонайменше одне слово з масиву. @BrokenGlass
kirushan

1
З точки зору продуктивності, чи не parameters.Any(x => myStrings.Contains(x.source));краще, ніж ваш перший приклад?
Флуппе

3

Ось зразок, щоб дізнатися, чи є елементи відповідності в іншому списку

List<int> nums1 = new List<int> { 2, 4, 6, 8, 10 };
List<int> nums2 = new List<int> { 1, 3, 6, 9, 12};

if (nums1.Any(x => nums2.Any(y => y == x)))
{
    Console.WriteLine("There are equal elements");
}
else
{
    Console.WriteLine("No Match Found!");
}

2
Зверніть увагу, що якщо залучені списки великі, це в кінцевому підсумку буде набагато повільнішим, ніж Intersectпідхід, оскільки це O (N * M) у розмірах списків. (Хоча це O (1) на згадку.)
Джон Скіт,

1

Якщо обидва списки занадто великі, і коли ми використовуємо вираз lamda, тоді завантаження займе багато часу. Краще використовувати linq у цьому випадку для отримання списку параметрів:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.