Класс Enumerable LINQ - Проверка последовательностей

ОГЛАВЛЕНИЕ

Проверка последовательностей

Некоторые приложения требуют проверки того факта, что в пределах последовательности соблюдаются определенные условия. Отвечает ли критериям какой-нибудь элемент? Отвечают ли критериям все элементы? Присутствует ли в последовательности некоторый конкретный элемент? Совпадают ли две последовательности? Класс Enumerable предоставляет методы, обеспечивающие получение всех этих сведений.

Для определения факта наличия в последовательности хотя бы одного элемента следует вызвать метод Enumerable.Any без параметров. Для передачи условия и определения того, отвечают ли этому условию какие-нибудь элементы в данной последовательности, методу следует передать функцию. Метод возвращает значение True (истина), если какие-нибудь элементы во входной последовательности присутствуют или соответствуют переданному условию (см. рис. 5).

Рис. 5 Поиск последовательности

' From AnyDemo in sample:
Dim db As New SimpleDataContext
Dim results = _
  From product In db.Products _
  Where product.CategoryID = 1

' Determine if a list has any elements:
Dim anyElements = results.Any()

' Call as extension method or shared method
' of IEnumerable:
Dim matchingElements = _
  results.Any(Function(prod) prod.ProductName.StartsWith("M"))
matchingElements = _
  Enumerable.Any(results, _
  Function(prod As Product) prod.ProductName.StartsWith("M"))

Для определения того, отвечают ли критерию все члены последовательности, вызовите метод Enumerable.All, передавая ему функцию, указывающую условие. В следующем примере определяется, все ли элементы результирующей коллекции имеют значение UnitsInStock больше 5.

' From AllDemo in sample:
' Is it true that all products have more than 5 units in stock?
Dim db As New SimpleDataContext
Dim results = _
  From product In db.Products _
  Where product.CategoryID = 1
Dim allElements = _
  results.All(Function(prod) CBool(prod.UnitsInStock > 5))

Для определения факта наличия в коллекции конкретного элемента следует вызвать метод Enumerable.Contains. Если выполняется поиск простого значения типа строки или целого числа, можно использовать блок сравнения по умолчанию, и вам понадобится только предоставить искомое значение. Если выполняется попытка определить, присуствует ли в коллекции более сложный объект, необходимо предоставить экземпляр класса, реализующего IEqualityComparer(Of T).

В примере кода на рис. 6 присутсвуют оба варианта вызова Enumerable.Contains. В первом примере просто определяется наличие в списке числа 5; во втором определяется, присутствует ли в списке продуктов элемент, соответствующий Chai (в этом примере используется тот же класс ProductComparer, который уже встречался в этой статье ранее).

Рис. 6 Поиск элементов в последовательности

'

From ContainsDemo in the sample:
' Simple check to see if list contains a value:
Dim numbers = Enumerable.Range(1, 10)
Dim contains5 = numbers.Contains(5)

' More complex objects require more complex comparison:
Dim db As New SimpleDataContext
Dim results = _
  From product In db.Products _
  Where product.CategoryID = 1

Dim item As New Product _
  With {.ProductID = 1, .ProductName = "Chai"}
Dim containsChai = results.Contains(item, New ProductComparer())

Для определения того, являются ли две последовательности одинаковыми, вызовите метод Enumerable.SequenceEqual. Точно так же, как в методе Enumerable.Contains, можно сравнивать либо две последовательности простых значений, используя блок сравнения по умолчанию, либо две последовательности более сложных объектов с помощью пользовательского блока сравнения.

Если две последовательности содержат данные разных типов или имеют разные длины, сравнение незамедлительно завершается ошибкой. Если они содержат данные одного и того же типа и имеют одинаковую длину, метод Enumerable.SequenceEqual сравнивает все элементы с помощью указанного блока сравнения. На рис. 7 показаны оба варианта вызова метода Enumerable.SequenceEqual. В обоих случаях возвращается значение False (ложь).

Рис. 7 Сравнение последовательностей

' From SequenceEqualDemo in sample:
Dim rnd As New Random
Dim start = rnd.Next

Dim count = 10
Dim s1 = Enumerable.Range(start, count)

' Choose a different random starting point:
start = rnd.Next
Dim s2 = Enumerable.Range(start, count)
Dim sequencesEqual = s1.SequenceEqual(s2)
sw.WriteLine("sequencesEqual = {0}", sequencesEqual)

' What if there's no default comparer? Must use your own:
Dim products1 = _
  From prod In db.Products _
  Where prod.CategoryID = 1
Dim products2 = _
  From prod In products1 _
  Where prod.UnitPrice > 5

sequencesEqual = _
  products1.SequenceEqual(products2, New ProductComparer())
sw.WriteLine("sequencesEqual = {0}", sequencesEqual)

Свою следующую статью я собираюсь посвятить оставшимся методам класса Enumerable, включая некоторые забавные методы, выполняющие полезные операции над множествами. А пока вы можете загрузить пример приложения и подвергнуть испытанию методы класса Enumerable. Они наверняка пригодятся вам при работе со структурами данных в Visual Studio 2008.

Автор: Кен Гетц (Ken Getz)
Источник: http://msdn.microsoft.com/ru-ru/magazine/