Множества операции над множествами программирование

Операции над множествами (C#)

Операции над множествами в LINQ — это операции запросов, результирующие наборы которых основываются на наличии или отсутствии эквивалентных элементов в одной или другой коллекции (или наборе).

Методы стандартных операторов запросов, которые выполняют операции над множествами, перечислены в следующем разделе.

Методы

Имена методов Описание Синтаксис выражения запроса C# Дополнительные сведения
Distinct или DistinctBy Удаляет повторяющиеся значения из коллекции. Не применяется Enumerable.Distinct
Enumerable.DistinctBy
Queryable.Distinct
Queryable.DistinctBy
Except или ExceptBy Возвращает разность множеств, т. е. элементы одной коллекции, которые отсутствуют во второй. Не применяется Enumerable.Except
Enumerable.ExceptBy
Queryable.Except
Queryable.ExceptBy
Intersect или IntersectBy Возвращает пересечение множеств, т. е. элементы, присутствующие в каждой из двух коллекций. Не применяется Enumerable.Intersect
Enumerable.IntersectBy
Queryable.Intersect
Queryable.IntersectBy
Union или UnionBy Возвращает объединение множеств, т. е. уникальные элементы, присутствующие в одной из двух коллекций. Не применяется Enumerable.Union
Enumerable.UnionBy
Queryable.Union
Queryable.UnionBy

Примеры

В некоторых из приведенных ниже примеров используется тип record , который представляет планеты Солнечной системы.

namespace SolarSystem; record Planet( string Name, PlanetType Type, int OrderFromSun) < public static readonly Planet Mercury = new(nameof(Mercury), PlanetType.Rock, 1); public static readonly Planet Venus = new(nameof(Venus), PlanetType.Rock, 2); public static readonly Planet Earth = new(nameof(Earth), PlanetType.Rock, 3); public static readonly Planet Mars = new(nameof(Mars), PlanetType.Rock, 4); public static readonly Planet Jupiter = new(nameof(Jupiter), PlanetType.Gas, 5); public static readonly Planet Saturn = new(nameof(Saturn), PlanetType.Gas, 6); public static readonly Planet Uranus = new(nameof(Uranus), PlanetType.Liquid, 7); public static readonly Planet Neptune = new(nameof(Neptune), PlanetType.Liquid, 8); // Yes, I know. not technically a planet anymore public static readonly Planet Pluto = new(nameof(Pluto), PlanetType.Ice, 9); >

Для создания экземпляра позиционной записи record Planet требуются аргументы Name , Type и OrderFromSun . Существует несколько экземпляров планет static readonly типа Planet . Это удобные определения для хорошо известных планет. Элемент Type определяет тип планеты.

namespace SolarSystem; enum PlanetType < Rock, Ice, Gas, Liquid >; 

Distinct и DistinctBy

В следующем примере показано поведение метода Enumerable.Distinct применительно к последовательности строк. Возвращаемая последовательность содержит уникальные элементы из входной последовательности.

Читайте также:  Новости frontend разработки где читать

График, демонстрирующий поведение Distinct().

string[] planets = < "Mercury", "Venus", "Venus", "Earth", "Mars", "Earth" >; IEnumerable query = from planet in planets.Distinct() select planet; foreach (var str in query) < Console.WriteLine(str); >/* This code produces the following output: * * Mercury * Venus * Earth * Mars */ 

Вместо Distinct можно использовать DistinctBy , который принимает keySelector . keySelector используется как сравнительный дискриминатор для типа источника. Давайте рассмотрим следующий массив планет:

В следующем коде планеты разделяются на основе PlanetType . При этом отображается первая планета каждого типа:

foreach (Planet planet in planets.DistinctBy(p => p.Type)) < Console.WriteLine(planet); >// This code produces the following output: // Planet < Name = Mercury, Type = Rock, OrderFromSun = 1 >// Planet < Name = Jupiter, Type = Gas, OrderFromSun = 5 >// Planet < Name = Uranus, Type = Liquid, OrderFromSun = 7 >// Planet

В приведенном выше коде C#:

  • Массив Planet фильтруется по первому вхождению каждого уникального типа планеты.
  • Полученные экземпляры planet записываются в консоль.

Except и ExceptBy

В следующем примере показано поведение Enumerable.Except. Возвращаемая последовательность содержит только те элементы из первой входной последовательности, которых нет во второй.

Рисунок, показывающий действие Except().

string[] planets1 = < "Mercury", "Venus", "Earth", "Jupiter" >; string[] planets2 = < "Mercury", "Earth", "Mars", "Jupiter" >; IEnumerable query = from planet in planets1.Except(planets2) select planet; foreach (var str in query) < Console.WriteLine(str); >/* This code produces the following output: * * Venus */ 

Вместо Except можно использовать метод ExceptBy, который принимает две последовательности потенциально разнородных типов и keySelector . Тип keySelector совпадает с типом второй коллекции и используется как сравнительный дискриминатор для типа источника. Давайте рассмотрим следующий массив планет:

Planet[] planets = < Planet.Mercury, Planet.Venus, Planet.Earth, Planet.Jupiter >; Planet[] morePlanets = < Planet.Mercury, Planet.Earth, Planet.Mars, Planet.Jupiter >; 

Чтобы найти планеты из первой коллекции, которые не входят во вторую коллекцию, можно проецировать имена планет в виде коллекции second с прежним значением keySelector :

// A shared "keySelector" static string PlanetNameSelector(Planet planet) => planet.Name; foreach (Planet planet in planets.ExceptBy( morePlanets.Select(PlanetNameSelector), PlanetNameSelector)) < Console.WriteLine(planet); >// This code produces the following output: // Planet

В приведенном выше коде C#:

  • keySelector определяется как локальная функция static , которая различает имена планет.
  • Первый массив планет фильтруется, чтобы получить отсутствующие во втором массиве планеты, на основе имен планет.
  • Полученный экземпляр planet записывается в консоль.

Intersect и IntersectBy

В следующем примере показано поведение Enumerable.Intersect. Возвращаемая последовательность содержит элементы, общие для обеих входных последовательностей.

График, отображающий пересечение двух последовательностей.

string[] planets1 = < "Mercury", "Venus", "Earth", "Jupiter" >; string[] planets2 = < "Mercury", "Earth", "Mars", "Jupiter" >; IEnumerable query = from planet in planets1.Intersect(planets2) select planet; foreach (var str in query) < Console.WriteLine(str); >/* This code produces the following output: * * Mercury * Earth * Jupiter */ 

Вместо Intersect можно использовать метод IntersectBy, который принимает две последовательности потенциально разнородных типов и keySelector . keySelector используется как сравнительный дискриминатор для типа второй коллекции. Давайте рассмотрим следующий массив планет:

Planet[] firstFivePlanetsFromTheSun = < Planet.Mercury, Planet.Venus, Planet.Earth, Planet.Mars, Planet.Jupiter >; Planet[] lastFivePlanetsFromTheSun = < Planet.Mars, Planet.Jupiter, Planet.Saturn, Planet.Uranus, Planet.Neptune >; 

Существует два массива планет, один из которых представляет первые пять планет от Солнца, а второй — последние пять планет. Так как тип Planet является позиционным типом record , вы можете использовать его семантику сравнения значений в формате keySelector :

foreach (Planet planet in firstFivePlanetsFromTheSun.IntersectBy( lastFivePlanetsFromTheSun, planet => planet)) < Console.WriteLine(planet); >// This code produces the following output: // Planet < Name = Mars, Type = Rock, OrderFromSun = 4 >// Planet

В приведенном выше коде C#:

  • Два массива Planet пересекаются с использованием семантики сравнения их значений.
  • В результирующей последовательности содержатся только те планеты, которые обнаружены в обоих массивах.
  • Полученные экземпляры planet записываются в консоль.

Union и UnionBy

В следующем примере показана операция объединения двух последовательностей строк. Возвращаемая последовательность содержит уникальные элементы из обеих входных последовательностей.

График, показывающий объединение двух последовательностей.

string[] planets1 = < "Mercury", "Venus", "Earth", "Jupiter" >; string[] planets2 = < "Mercury", "Earth", "Mars", "Jupiter" >; IEnumerable query = from planet in planets1.Union(planets2) select planet; foreach (var str in query) < Console.WriteLine(str); >/* This code produces the following output: * * Mercury * Venus * Earth * Jupiter * Mars */ 

Вместо Union можно использовать метод UnionBy, который принимает две последовательности одного типа и keySelector . keySelector используется как сравнительный дискриминатор для типа источника. Давайте рассмотрим следующий массив планет:

Planet[] firstFivePlanetsFromTheSun = < Planet.Mercury, Planet.Venus, Planet.Earth, Planet.Mars, Planet.Jupiter >; Planet[] lastFivePlanetsFromTheSun = < Planet.Mars, Planet.Jupiter, Planet.Saturn, Planet.Uranus, Planet.Neptune >; 

Чтобы объединить эти две коллекции в одну последовательность, укажите keySelector :

foreach (Planet planet in firstFivePlanetsFromTheSun.UnionBy( lastFivePlanetsFromTheSun, planet => planet)) < Console.WriteLine(planet); >// This code produces the following output: // Planet < Name = Mercury, Type = Rock, OrderFromSun = 1 >// Planet < Name = Venus, Type = Rock, OrderFromSun = 2 >// Planet < Name = Earth, Type = Rock, OrderFromSun = 3 >// Planet < Name = Mars, Type = Rock, OrderFromSun = 4 >// Planet < Name = Jupiter, Type = Gas, OrderFromSun = 5 >// Planet < Name = Saturn, Type = Gas, OrderFromSun = 6 >// Planet < Name = Uranus, Type = Liquid, OrderFromSun = 7 >// Planet

В приведенном выше коде C#:

  • Эти два массива Planet объединяются с использованием семантики сравнения значений record .
  • Полученные экземпляры planet записываются в консоль.

См. также

Источник

Программирование — 07 — Множества

Множество — это структурированный тип данных, представляющий набор взаимосвязанных по какому-либо признаку (или группе признаков) элементов, которые можно рассматривать как единое целое.

Все элементы множества должны принадлежать одному из скалярных типов, кроме вещественных (и других скалярных типов, число элементов которых превышает 256). Этот тип называется базовым типом множества. Количество элементов множества не должно превышать 256. Поэтому нельзя использовать в качестве базового типа типы, количество элементов которых превышает 256 (например, Integer), для таких типов в качестве базового типа можно использовать диапазоны или перечисления из их значений.

Область значений переменных типа множество набор всевозможных подмножеств, составленных из элементов базового типа. Если базовый тип принимает N значений, то тип множество для него будет иметь вариантов различных значений (порядок элементов в подмножествах не учитывается).

имя_типа_множество = set of базовый_тип ;

имя_множества : имя_типа_множество ;

имя_множества : set of базовый_тип ;

Пример 7.1 ( описания множеств ):

Chislo = set of 1..31 ;

LatBold = set of ‘A’ .. ’Z’ ;

Col = set of ( Red, Green, Blue ) ;

Day = ( Mon, Tues, Wed, Thur, Fri, Sat, Sun ) ;

WorkDay = set of Mon .. Fri ;

Ch1, Ch2 : Chislo ;

LatB1 : LatBold ;

C1, C2, C3 : Col ;

WD1, WD2, WD3, WD4 : WorkDay ;

KirB : set of ‘А’..’Я’ ;

Выражения с множествами

Значения типа множество могут быть вычислены из других значений типа множество с помощью выражений и присвоены переменным с помощью оператора присваивания. Множественные выражения состоят из операндов множественного типа и операций над множествами.

Операнды множественного типа:

  • переменные типа множество;
  • множественные конструкции (множественные константы).

Множественная конструкция — это одна или несколько спецификаций элемента, разделенных запятыми и заключенных в квадратные скобки. Спецификация элемента — это выражение того же типа, что и базовый тип множества, или диапазон, записанный как два таких выражения, разделенных двумя последовательными точками. Например, [ 1, 2, 5, 17 ] [ 1..50 ] [ 1..5, 10..100 ] [ x+y..2*x+3*y ] [ ‘P’, ‘a’, ‘s’, ‘c’, ‘a’, ‘l’ ] [ ‘A’..’Z’ ] [ ] — пустое множество Над множествами определены следующие операции согласно приоритету:

  1. * (пересечение: );
  2. + (объединение: );

– (относительное дополнение — разность множеств: \ );

  1. операции отношения:

= (проверка равенства множеств); <> (проверка неравенства множеств); = (проверка включения одного множества в другое); in (проверка принадлежности элемента множеству). Примеры 7.2 ( операции над множествами ):

A B Операция Результат
[ 1, 2, 3 ] [ 2, 3, 4 ] A*B [ 2, 3 ]
A B Операция Результат
[ 1, 2, 3 ] [ 2, 3, 4 ] A+B [ 1, 2, 3, 4 ]
A B Операция Результат
[ 1, 2, 3 ] [ 2, 3, 4 ] AB [ 1 ]
A B Операция Результат
[ 1, 2, 3 ] [ 2, 3, 4 ] A=B False
[ 1, 2, 3 ] [ 1, 2, 3 ] A=B True
[ a’..’z ] [ a’..’z ] A=B True
[ a’..’z ] [ b’..’z ] A=B False
A B Операция Результат
[ 1, 2, 3 ] [ 2, 3, 4 ] A<>B True
[ 1, 2, 3 ] [ 1, 2, 3 ] A<>B False
[ a’..’z ] [ a’..’z ] A<>B False
[ a’..’z ] [ b’..’z ] A<>B True
A B Операция Результат
[ 1, 2, 3, 4 ] [ 2, 3, 4 ] A>=B True
[ 1, 2, 3 ] [ 2, 3, 4 ] A>=B False
A B Операция Результат
[ 2, 3, 4 ] [ 1, 2, 3, 4 ] AB True
[ 2, 3, 4 ] [ 1, 2, 3 ] AB False
N A Операция Результат
3 [ 2, 3, 4 ] N in A True
1 [ 2, 3, 4 ] N in A False
’d [ b’..’z ] N in A True
’a [ b’..’z ] N in A False

Иногда указанных операций над множествами может быть недостаточно для решения задачи. В таких случаях нужно написать нужные процедуры обработки множеств. Процедуры работы с множествамиProcedure.

Include ( varMySet : set of T;IncSubSet : T);
добавляет к множеству MySet подмножество IncSubSet, где MySet — переменная типа множество любого допустимого базового типа T; IncSubSet — выражение типа T
Exclude ( varMySet : set of T;IncSubSet : T);
удаляет из множества MySet подмножество IncSubSet

Указанные процедуры можно не использовать — аналогичных результатов можно добиться, используя только операции над множествами. Использование множеств Использование множеств в программах дает следующие преимущества:

  • значительно упрощаются сложные операторы if;
  • увеличивается наглядность программы и понимание алгоритма решения задачи;
  • в ряде случаев экономится память, время компиляции и выполнения (объем памяти, занимаемый одним элементом множества, составляет 1 бит; множественные операции выполняются быстрее).

Недостатки использования множеств объясняются тем, что ввод-вывод множеств не поддерживается языком Паскаль. Для этого нужно писать соответствующие процедуры. При этом если множество состоит из элементов стандартных скалярных типов, особых проблем не возникает. При использовании же скалярных типов пользователя разработка процедур ввода-вывода для множеств довольно сложна и требует много времени и памяти. Пример. Требуется создать множество из элементов типа Char (выход из фазы создания осуществить при вводе значения ‘z’); найти в нем элемент с минимальным номером в таблице кодов; распечатать все элементы созданного множества в алфавитном порядке. Управление работой программы осуществить из меню. ProgramDemoSet;VarS:set of Char ;N,Rejim: Char ;ProcedureKonstr;Begin Writeln ( ‘Вводите элементы множества из букв a..z; символ z – окончание ввода’ ) ;S:= [ ];While True doBegin ReadLn ( N ) ;S:= S + [ N ] ;IfN = zthen Exit endEnd;ProcedureMinS;BeginN:= ‘ ‘;While not ( N in S ) doN:= Succ( N ) ; Writeln ( Элемент с минимальным номером = ,N ) End;ProcedureRasp;BeginForN:= ato ‘z’ doIfN in SThen wtiteln ( N ) End;BeginWhile True doBegin Writeln ( 1 – Создание ) ; Writeln ( 2 – Поиск Эл-та с мин-м номером ) ; Writeln ( 3 – Вывод Эл-ов мн-ва ) ; Writeln ( 4 – Выход из программы ) ; Readln ( Rejim ) ;CaseRejimof ‘1:Konstr; ‘2:MinS; ‘3:Rasp; ‘4: Halt endEndEnd.

Источник

Оцените статью