2011-12-22 5 views
31

que tienen una matriz de objetos de la siguiente estructura:Unión e intersección en PowerShell?

structure Disk 
{ 
    int UID; 
    String Computer; 
} 

Un equipo puede tener un montón de discos compartidos, y un disco pueden ser compartidos entre los ordenadores.

Quiero encontrar todos los discos comunes a todas las computadoras. Por ejemplo, tengo la computadora A, B y C; Discos 1, 2 y 3. La matriz de discos es {1, A}, {1, B}, {2, A}, {2, B}, {2, C}, {3, A}. El resultado que deseo debe ser el disco 2, porque aparece en A, B y C.

¿Existe una forma efectiva de lograr esto?

Con múltiples bucles foreach es posible, pero definitivamente quiero una mejor manera. Estoy pensando en operaciones como la intersección, pero no encontré esto en PowerShell.

+1

Yo recomendaría cambiar el título a "Unión, intersección y diferencia/Establecer resta en PowerShell". Así que tendremos todas las operaciones establecidas en un solo lugar. –

+0

Basado en la pregunta y sugerencias aquí, he creado una función de PowerShell para hacer Union, Intersection y Minus para objetos. Échale un vistazo: https://sqljana.wordpress.com/2015/09/23/perform-set-operations-union-intersection-minus-complement-using-powershell/ –

Respuesta

56

Suponiendo $arr es la matriz, puede hacerlo de esta manera:

$computers = $arr | select -expand computer -unique 
$arr | group uid | ?{$_.count -eq $computers.count} | select name 

En general, me acercaría unión e intersección en Powershell así:

$a = (1,2,3,4) 
$b = (1,3,4,5) 
$a + $b | select -uniq #union 
$a | ?{$b -contains $_} #intersection 

Pero por lo usted está preguntando, la solución anterior funciona bien y no realmente acerca de la unión y la intersección en la definición estándar de los términos.

Actualización:

He escrito pslinq que proporciona Union-List y Intersect-List que ayudan a lograr establecer la unión y la intersección con Powershell.

+0

Qué cosas más geniales, cómo trabajarían estos oneliner con las colecciones con clave como Hashtables? – Bastl

+1

Publicación excelente: debe haber una biblioteca estándar para matrices que proporcione funcionalidades como esa. Lodash para Powershell. – ferr

+1

para completar puede obtener la diferencia establecida entre $ a y $ b usando $ a | ? {$ b -notcontains $ _} #difference –

11

También puede hacer

$a = (1,2,3,4) 
$b = (1,3,4,5) 
Compare-Object $a $b -PassThru -IncludeEqual     # union 
Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent # intersection 

no funciona si $a es nulo sin embargo.

+1

Podría agregar $ null a la matriz. $ a = 1,2,3,4, $ null –

10

Para el sistema de resta (a - b):

$a | ?{-not ($b -contains $_)}

+7

También hay -notcontains. –

3

Si bien esto no va a funcionar en las primeras versiones, en las versiones más recientes que sólo puede llamar a las funciones de extensión .NET LINQ directamente, por ejemplo,

[system.linq.enumerable]::union([object[]](1,2,3),[object[]](2,3,4)) 

(Sin el molde a algún tipo enumerable, PowerShell genera un error "no puede encontrar sobrecarga".)

Esto definitivamente funciona en PowerShell V4 y V5 y, definitivamente, no lo hace en V2. No tengo un sistema a mano con V3.

Cuestiones relacionadas