PowerShell: пересечение более двух массивов
Используя PowerShell, у меня есть 14 массивов строк. Некоторые массивы пусты. Как мне получить пересечение (все элементы, которые существуют во всех массивах) этих массивов (исключая пустые массивы)? Я пытаюсь избежать сравнения двух массивов одновременно.
Некоторые массивы пусты, поэтому я не хочу включать их в свои сравнения. Любые идеи о том, как я подошел бы к этому? Спасибо.
Моя попытка решить эту проблему (хотя она не проверяет пустые массивы):
Мой желаемый результат состоит в том, что test и test2 отображаются в $overlap. Это решение не работает, потому что оно не проверяет, пуст ли сравниваемый массив.
3 ответа
Примечание. Далее предполагается, что ни один отдельный массив не содержит одну и ту же строку более одного раза (для решения этой проблемы потребуется дополнительная работа).
Приведенное выше выводит те строки, которые присутствуют во всех из непустых входных массивов:
Вы близко. Исключение пустых массивов из сравнения важно, потому что пересечение пустого массива и любого другого массива является пустым массивом, и как только $overlap содержит пустой массив, это будет окончательный результат независимо от того, что последующие массивы содержат.
Вот ваш код с непустой проверкой и переписанный с использованием циклов.
Вот решение с использованием Hashset . Hashset – это коллекция, в которой хранятся только уникальные элементы и обеспечивается быстрый поиск, что делает ее хорошим выбором для расчета пересечений. У него даже есть метод IntersectWith , который принимает любой перечисляемый тип (например, массив) в качестве аргумента. Метод изменяет исходный Hashset , чтобы он содержал только те элементы, которые содержатся как в Hashset , так и в аргументе, переданном методу.
Вывод:
Чтобы отфильтровать пустые массивы (или вообще любую коллекцию), мы проверяем ее элемент Count , который дает количество элементов.
.Foreach и .Where являются PowerShell внутренние методы. Они могут быть быстрее, чем команды ForEach-Object и Where-Object , особенно при работе непосредственно с коллекциями (в отличие от вывода другой команды). Автоматическая переменная $_ , как обычно, представляет текущий элемент коллекции.
Этот код, использующий команды конвейера, функционально такой же:
В if( $null -eq $overlap ) очень важно, чтобы $null находился слева от оператора -eq . Если бы он был справа, PowerShell выполнил бы поэлементное сравнение с $null с элементами filter вместо проверки того, является ли сама переменная $overlap $null (см. Об операторах сравнения)
В строке $overlap = $_ PowerShell автоматически преобразует текущий массив в Hashset , потому что мы установили ограничение типа с помощью [Collections.Generic.Hashset[object]] $overlap ранее, а array преобразуется в Hashset (см. О переменных).
Сравнение строк Hashset по умолчанию с учетом регистра. Чтобы сделать его нечувствительным к регистру, преобразуйте каждую строку в нижний регистр следующим образом:
При этом используется перечисление доступа к члену для вызова метода String.ToLower() для каждого элемента входных массивов.
В первом варианте вставка разрыва строки перед Where и ForEach на самом деле не требуется, но улучшает читаемость кода (обратите внимание, что вы не можете вставить разрыв строки перед .Where и .ForEach , потому что это сбивает с толку анализатор PowerShell).
Union and Intersection in PowerShell?
I have an array of objects of the following structure:
A computer may have a bunch of shared disks, and a disk may be shared among computers.
I want to find out all the disks common to all the computers. For example, I have computer A, B, and C; Disks 1, 2, and 3. The disk array is <1,A>, <1,B>, <2,A>,<2,B>,<2,C>,<3,A>. The result that I want should be the disk 2, because it appears on A, B, and C.
Is there a effective way to achieve this?
With multiple foreach loops it’s achievable, but definitely I want a better way. I’m thinking about operations like intersection, but didn’t find this in PowerShell.
Объединение и пересечение в PowerShell?
У компьютера может быть несколько общих дисков, и один диск может быть общим для нескольких компьютеров.
Я хочу узнать все диски, общие для всех компьютеров. Например, у меня есть компьютеры A, B и C; Диски 1, 2 и 3. Дисковый массив <1,A>, <1,B>, <2,A>,<2,B>,<2,C>,<3,A>. Результат, который я хочу, должен быть диском 2, потому что он появляется на A, B и C.
Есть ли эффективный способ добиться этого?
С несколькими циклами foreach это достижимо, но определенно мне нужен лучший способ. Я думаю о таких операциях, как пересечение, но не нашел этого в PowerShell.
Я бы порекомендовал изменить заголовок на «Объединение, пересечение и разность/установить вычитание в PowerShell». Таким образом, у нас будут все операции над наборами в одном месте. — Mehrdad Mirreza
Powershell как сделать пересечение двух массивов
Буду очень благодарна за любую помощь.
Дополнение:
Общий вид html-таблицы:
.csv выглядит примерно следующим образом:
0000000000000060186082;AccessPoint Cisco Catalyst 92120AXI ;AccessPoint/Repeater; 700,00 ; 833,00
Что сейчас выводит скрипт: 