2014-07-15 19 views
9

Sto faticando un po 'a rimuovere la prima riga (elemento ID) di un array.PowerShell Rimuovi elemento [0] da un array

$test.GetType() 

IsPublic IsSerial Name          BaseType                          
-------- -------- ----          --------                          
True  True  Object[]         System.Array 

per elencare tutte le opzioni che ho provato ,$test | gm e afferma chiaramente:

Remove   Method    void IList.Remove(System.Object value)                        
RemoveAt  Method    void IList.RemoveAt(int index) 

Così quando provo $test.RemoveAt(0) ottengo l'errore:

Exception calling "RemoveAt" with "1" argument(s): "Collection was of a fixed size."At line:1 char:1 
+ $test.RemoveAt(1) 
+ ~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : NotSupportedException 

Così ho finalmente trovato here che il mio array deve essere del tipo System.Object per poter utilizzare $test.RemoveAt(0). È buona pratica dichiarare tutti gli array all'inizio della sceneggiatura come una lista? O è meglio convertire gli array con $collection = ({$test}.Invoke()) in un elenco più avanti quando questa funzionalità è necessaria?

Quali sono i pro ei contro di entrambi i tipi? Grazie per l'aiuto.

risposta

15

Gli array sono di dimensioni fisse, come dice l'errore. RemoveAt() è un metodo ereditato che non si applica agli array normali. Per rimuovere la prima voce nella matrice, si potrebbe sovrascrivere la matrice da una copia che comprende tutte le voci tranne la prima, in questo modo:

$arr = 1..5 

$arr 
1 
2 
3 
4 
5 

$arr = $arr[1..($arr.Length-1)] 

$arr 
2 
3 
4 
5 

Se è necessario rimuovere i valori a diversi indici, allora si dovrebbe considerare l'utilizzo di un List. Supporta Add(), Remove() e RemoveAt(): per maggiori dettagli su come il lavoro array

#If you only have a specific type of objects, like int, string etc. then you should edit `[System.Object] to [System.String], [int] etc. 
$list = [System.Collections.Generic.List[System.Object]](1..5) 

$list 
1 
2 
3 
4 
5 

$list.RemoveAt(0) 

$list 
2 
3 
4 
5 

Vedi mio precedente SO answer e about_Arrays.

1

Penso che dipenderà dalle circostanze. Se avete solo bisogno di rimuovere tale primo elemento, una volta, quindi è possibile utilizzare array di affettare:

$arr = $arr[1..($arr.length-1)] 

Se avete intenzione di farlo più volte, allora si dovrebbe iniziare con un ArrayList o un insieme generico. Se si tratta di un array di grandi dimensioni, potresti semplicemente mettere l'espressione che lo sta creando in un blocco di script e fare un .invoke() su quello invece di consentire alla pipeline di creare un array e quindi convertirlo in una raccolta.

0

Scusate la risposta in ritardo, ma anche io stavo lottando con questo. Per quanto mi riguarda (scrivendo in un file di testo), mi sono reso conto che dal momento che la matrice era una dimensione fissa - invece di rimuoverla, potrei semplicemente impostare il valore su string.empty.

$results = SQLQuery -connectionString $connectionString -query $query; 
$results[0] = ''; 
foreach ($r in $results) { 
    Add-Content $skus $r[0]; 
} 

Per me questo ha eliminato l'intestazione che non volevo nel mio file flat. Spero che questo aiuti qualcun altro là fuori.

2

solo per aggiornare - c'è un problema con il @Frode F. answer

If the number of elements in array is more than 1

$arr = $arr[1..($arr.Length-1)] 

If the number of elements is 1, then this doesn't remove the element

if($arr.Length -le 1) { 
    $arr = @() 
} 
else { 
    $arr = $arr[1..($arr.length - 1)] 
} 
7

Questo vi permetterà di rimuovere ogni occorrenza di un elemento arbitrario da una matrice senza ricorrere a un più sofisticato Oggetto .NET.

$x=<array element to remove> 
$test = $test | Where-Object { $_ -ne $test[$x] } 

Questo farà lo stesso, ma rimuoverà solo uno degli elementi. Se ci sono duplicati, rimarranno.

$x=<array element to remove> 
$skip=$true 
$test = $test | ForEach-Object { if (($_ -eq $x) -and $skip) { $skip=$false } else { $_ } } 
+0

In seguito, questo ha fatto il trucco per me. Ed è bello e conciso. – Spikee

+0

Ciò può comportarsi in modo errato se la matrice contiene valori duplicati. –

+0

@RonMacNeil, buon punto. Ho aggiornato la mia risposta. –