2010-07-27 16 views
6

ho voluto recidere tutti, ma i primi cinque elementi di un array, così ho stupidamente fatto:Perl linguaggio per ottenere un numero massimo di elementi di un array

@foo = @foo[ 0 .. 4 ]; 

e vivamente apprezzato la mia intelligenza. Ma quello si è rotto una volta che @foo è finito con solo tre elementi, perché poi ho finito con due undef s alla fine, invece di un array di tre elementi. Così l'ho cambiato in:

@foo = @foo > 5 ? @foo[ 0 .. 4 ] : @foo; 

Questo funziona ma è un pò brutto. C'è un modo migliore per dire "dammi tutto fino ai primi cinque elementi dell'array?"

+0

E 'solo perché non sono un madrelingua inglese che trovo il titolo della domanda abbastanza insoddisfacente? Mi aspetto che i lettori veloci (incluso Google) ottengano questo come "idioma Perl per ottenere il numero massimo da un array" – Wolf

risposta

8

È possibile impostare l'ultimo indice di un array di accorciare o allungare esso. Come il tuo codice, dovrai verificarlo per assicurarti di non creare elementi non definiti.

$#foo = 4 if $#foo > 4; 
+0

Interessante prendere su questo !! Non sono sicuro che mi piaccia più di 'splice()', ma mi piace che sia unico. –

+0

Mi ero dimenticato di questo! :) +1 – Axeman

+0

Fantastico. Mi piace molto questo. – friedo

6

Se non si cura di mutazioni (impliciti nei LHS autoreferenziali @foo = qualcosa di riferimento @foo) utilizzare i due argomenti splice(), vedere perldoc -f splice per maggiori informazioni.

splice ARRAY, OFFSET

rimuove gli elementi specificati da offset e LENGTH da una matrice, e li sostituisce con gli elementi di LISTA eventuali. In contesto elenco, restituisce gli elementi rimossi dall'array. In contesto scalare, restituisce l'ultimo elemento rimosso, o "undef" se non vengono rimossi elementi. L'array cresce o si restringe se necessario. Se OFFSET è negativo, inizia così lontano dalla fine dell'array. Se LENGTH viene omesso, rimuove tutto da OFFSET in poi. Se LENGTH è negativo, rimuove gli elementi da OFFSET in avanti eccetto per gli elementi -LENGTH alla fine dell'array. Se entrambi OFFSET e LENGTH vengono omessi, rimuove tutto. Se OFFSET è oltre la fine dell'array, perl emette un avviso e giunge alla fine dell'array.

Poi guarda l'effetto:

@_ = 1..10; 
splice @_, 5; 
say for @_; 


@_ = 1..3; 
splice @_, 5; 
say for @_; 

Se stai usando warnings, e spero che si dovrà verificare la lunghezza (come nel suggerimento di ascia) o disattivare l'avviso rumoroso (splice() compensato oltre la fine dell'array):

{ 
    no warnings 'misc'; 
    splice @_, 5; 
} 
+0

Mi dimentico sempre di 'splice' – friedo

+0

Sì, sembra un po 'circolare da fare' @foo = @foo [stuff ; ] ', la giuntura sarà enormemente più veloce. –

+0

Sfortunatamente questo produce l'avviso "splice() offset passato alla fine dell'array", quindi si consiglia di aggiungere un '$ SIG locale {__ WARN __}' quando si esegue questa operazione, o eseguire un controllo della lunghezza come ha detto Axeman. – Ether

1

questo non è che aggraziata, ma si può esprimere in questo modo:

@foo[ 0..($#foo > 4 ? 4 : $#foo) ]; 

Una funzione generalizzata min potrebbe sembrare migliore.

use List::Util qw<min>;  
@foo[ 0..min($#foo, 4) ]; 

Ma se si desidera solo per sbarazzarsi di tutto il resto, allora non vi resta che splice fuori il resto:

splice(@foo, 5) if 5 < @foo; 
6

Ancora un altro modo:

@foo = splice(@foo, 0, 5); 

A differenza di altro suggerimento per il cambio, questo non fa scattare un avvertimento; il 5 significa esplicitamente "fino a 5".

+0

espressione più esplicita di ciò che si desidera [splice - perldoc.perl.org] (https://perldoc.perl.org/functions/splice.html) è anche la soluzione più breve dal punto di vista psicologico;) – Wolf

Problemi correlati