2011-12-22 17 views
31

Ho un array di oggetti della seguente struttura:Unione e intersezione in PowerShell?

structure Disk 
{ 
    int UID; 
    String Computer; 
} 

Un computer può avere un gruppo di dischi condivisi, e un disco può essere condiviso tra i computer.

Voglio scoprire tutti i dischi comuni a tutti i computer. Ad esempio, ho computer A, B e C; Dischi 1, 2 e 3. L'array del disco è {1, A}, {1, B}, {2, A}, {2, B}, {2, C}, {3, A}. Il risultato che voglio dovrebbe essere il disco 2, perché appare su A, B e C.

Esiste un modo efficace per raggiungere questo obiettivo?

Con più cicli foreach è possibile, ma sicuramente voglio un modo migliore. Sto pensando a operazioni come l'intersezione, ma non ho trovato questo in PowerShell.

+1

Si consiglia di modificare il titolo in "Unione, intersezione e differenza/Imposta sottrazione in PowerShell". Quindi avremo tutte le operazioni in un posto. –

+0

In base alla domanda e ai suggerimenti qui riportati, ho creato una funzione di PowerShell per fare Union, Intersection e Minus per gli oggetti. Dai un'occhiata a: https://sqljana.wordpress.com/2015/09/23/perform-set-operations-union-intersection-minus-complement-using-powershell/ –

risposta

56

Supponendo $arr è la matrice, si può fare in questo modo:

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

In generale, vorrei avvicinare unione e intersezione in PowerShell come questo:

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

Ma per quale stai chiedendo, la soluzione di cui sopra funziona bene e non riguarda davvero l'unione e l'intersezione nella definizione standard dei termini.

Aggiornamento:

Ho scritto pslinq che fornisce Union-List e Intersect-List che aiutano a raggiungere impostare unione e intersezione con PowerShell.

+0

Cose interessanti, come funzionano questi oneliner con le raccolte con chiave come Hashtables? – Bastl

+1

Ottimo post: dovrebbe esserci una libreria standard per gli array che fornisce funzionalità come questa. lodash per powershell .. – ferr

+1

per completezza è possibile ottenere la differenza tra $ a e $ b usando $ a | ? {$ b -non contiene $ _} #differenza –

11

si può anche fare

$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 

non funziona se $a è null però.

+1

Potrebbe aggiungere $ null all'array. $ a = 1,2,3,4, $ null –

10

Per set sottrazione (a - b):

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

+7

C'è anche -notcontains. –

3

Anche se questo non funzionerà nelle prime versioni, nelle versioni più recenti si può chiamare direttamente le funzioni di estensione .NET LINQ, per esempio

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

(Senza il getto a qualche tipo enumerable, PowerShell genera un errore "non può trovare sovraccarico".)

Questo funziona sicuramente in PowerShell V4 e V5 e sicuramente non fa in V2. Non ho un sistema a portata di mano con V3.