2013-10-17 8 views
8

Ho un array ordinato in uno script perl per esempio:modo pulito per dividere una serie in tre parti e visualizzare all'utente

qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll) 

C'è un modo semplice per visualizzare in tre colonne in modo che

  1. primo terzo è nella colonna di sinistra
  2. metà terzo è nella colonna centrale
  3. e l'ultimo terzo è in colonna di destra

Questo è così gli elementi possono essere visualizzati scorrendo lungo lo schermo anziché attraverso di esso. ad esempio

aaa eee iii 
bbb fff jjj 
ccc ggg kkk 
ddd hhh lll 

ho cercato di usare il modulo ma è sempre complicato e pensato che ci potrebbe essere una soluzione elegante. In definitiva, intendo usarlo per qualcosa di simile a select in bash.

Grazie.

risposta

8
use List::MoreUtils qw(part); 
my $num_rows = int(@a/3); 
my @aoa = map [ @a[@$_] ], part { $_ % $num_rows } 0..$#a; 
print("@$_\n") for @aoa; 

o

use List::MoreUtils qw(part); 
my $num_rows = int(@a/3); 
my @aoa = part { $_ % $num_rows } 0..$#a; 
print("@a[ @$_ ]\n") for @aoa; 

o

my $num_rows = int(@a/3); 
for my $row_num (0..$num_rows-1) { 
    print("@a[ map { $row_num + $num_rows*$_ } 0..2 ]\n"); 
} 

versioni di cui sopra che non assume @a% 3 == 0.

use List::MoreUtils qw(part); 
use POSIX   qw(ceil); 
my $num_rows = ceil(@a/3); 
my @aoa = map [ @a[@$_] ], part { $_ % $num_rows } 0..$#a; 
print("@$_\n") for @aoa; 

o

use List::MoreUtils qw(part); 
use POSIX   qw(ceil); 
my $num_rows = ceil(@a/3); 
my @aoa = part { $_ % $num_rows } 0..$#a; 
print("@a[ @$_ ]\n") for @aoa; 

o

use POSIX qw(ceil); 
my $num_rows = ceil(@a/3); 
for my $row_num (0..$num_rows-1) { 
    print("@a[ grep { $_ < @a } map { $row_num + $num_rows*$_ } 0..2 ]\n"); 
} 
+0

Grazie a ikegami, mi piace la tua ultima soluzione, per gli altri che usano 'ceil (@/3)' innesca una "Possibile interpolazione involontaria" se stai usando 'use strict' – David

+0

@David, quel messaggio proviene da avvertimenti, non severi, e il mio codice non lo produce. Hai cambiato qualcosa (erroneamente) se l'hai ottenuto. – ikegami

+0

non mi lamento, comunque sono tornato a giocare di nuovo con esso, e non riesco a ricreare l'errore che ho visto, quindi non ho idea di come sono riuscito a farlo! :) – David

3

Ecco la mia soluzione, spero che ti aiuti.

use strict; 
use warnings; 

my @arr = ("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll"); 
my $size = @arr; 

my $column = 3; 

my $mod = $size/$column; 

my $i = $size; 
my $count = 0; 
while ($i > 0) { 
    my $k = $count; 
    while ($k < $size) { 
     print "$arr[$k]\t"; 
     $k += $mod; 
    } 
    print "\n"; 
    $count++; 
    $i -= $column; 
} 
+0

Grazie Lightbringer, Ecco alcune note sulla vostra soluzione: Aggiunta di elementi in più per la matrice fa apparire articoli alla fine di una colonna e la parte superiore della successiva, l'aggiunta di elementi più lunghi fa sì che le colonne perdano allineamento – David

3
my @foo = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll); 
my $rows = int((@foo+2)/3); 
my @row; 
$row[$_ % $rows][$_/$rows] = $foo[$_] for 0..$#foo; 
for my $row (@row) { 
    print join(' ', @$row), "\n"; 
} 
+0

Thansk ysth, ecco alcune note su questa soluzione: Gli oggetti extra vengono gestiti bene aggiungendo ex tra righe, le colonne non si allineano se gli elementi nella matrice non hanno la stessa larghezza. – David

2

Un'altra opzione:

use strict; 
use warnings; 

my @a = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll); 
my @aoa; 
push @{ $aoa[ $_ % 4 ] }, $a[$_] for 0 .. $#a; 
print "@{ $_ }\n" for @aoa; 
+0

Grazie Kenosis, Ecco alcune note sulla tua soluzione: Gli elementi di array aggiuntivi vengono aggiunti come un'altra colonna a sinistra, le colonne non si allineano se gli elementi nella matrice non hanno la stessa larghezza – David

4

Dopo aver letto questa domanda, sembrava un po 'come un example che ho letto nel documenti per Perl6::Form. (Che è l'implementazione Perl5)

use strict; 
use warnings; 
use Perl6::Form; 

my @array = qw'aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll'; 

print form 
    "{[[[[[:} {:[[[[:} {:[[[[[}", 
    \@array, \@array, \@array; 
aaa  eee  iii 
bbb  fff  jjj 
ccc  ggg  kkk 
ddd  hhh  lll 

Non funzionerà come si vuole che, se una delle stringhe è più lungo di quanto sia stato assegnato per esso.

... 
$array[-1] .= ' lllllll'; 
... 
aaa  fff  kkk 
bbb  ggg  lll 
ccc  hhh  lllllll 
ddd  iii 
eee  jjj 

Naturalmente si potrebbe calcolare la larghezza desiderata prima della chiamata a form.

... 

use List::Util qw'max'; 

my $max_length = max 5, map length, @array; # at least 5 
my $TERMINAL_WIDTH = 80; 
my $number_of_cols = int($TERMINAL_WIDTH/($max_length+1)); 

my $single = '{:' . ('[' x ($max_length-4)) . ':} '; 

print $single, "\n\n"; # debug statement 

print form 
    $single x $number_of_cols, 
    (\@array) x $number_of_cols; 
{:[[[[[[[:} 

aaa   ccc   eee   ggg   iii   kkk 
bbb   ddd   fff   hhh   jjj   lll lllllll 
                      80^
0

4 LOC: molto semplice ... GODETEVI

my @tokens = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll); 
my $text = join(" ",@tokens); 
while($text =~ /[^ ]+ [^ ]+ [^ ]+/g) 
{ 
    print "$&\n"; 
} 

Samir

+0

Grazie Samir, Ecco le mie note sul tuo soluzione. Funziona bene quando divisibile per tre, ma elimina gli extra se non lo è. Le colonne non si allineano se gli elementi nella matrice non hanno la stessa larghezza. – David

Problemi correlati