Liste auf mehrere Spalten verteilt formatieren

Hallo liebe Perl-Experten,

Während meiner ersten Versuche mit Perl suche ich eine Lösung für eine weitere Aufgabe:
Wie kann man eine Liste so formatieren, dass ihre Elemente auf mehrere Spalten aufgeteilt werden? Ich möchte also Perl mitteilen, dass Beispielsweise nach der Ausgabe von je zwei Elementen wieder in die erste Zeilen gesprungen werden und eine neue Spalte begonnen werden soll. Die Elemente zweier Spalten sollen dabei einfach durch ein Leerzeichen getrennt sein, und brauchen nicht bündig zu stehen.
Minimalbeispiel:
Ausgangsliste:
A
B
C
D
E
F
Neu formatiert:
A C E
B D F

Vielen Dank schon mal für eure Hilfe!

Moin,

so etwa?

use strict;
use warnings;
use 5.010;

my @in = ;  
  
while (my @col = splice @in, 0, 3, ()) {  
 say "@col";  
}  

Grüße,
Moritz

Hallo Moritz,

Vielen Dank für deine schnelle Antwort. Die splice-Funktion von Perl kannte ich noch nicht und habe gleich mal den Eintrag im „Kamel-Buch“ (L. Wall, Programmieren mit Perl, O’Reilly) nachgeschlagen und wieder mal was neues gelernt.
Dein Codeschnipsel teilt mir aber leider trotzdem nicht den Text auf drei Spalten auf, sondern liefert mir die Elemente, die eigentlich in der zweiten und dritten Spalten erscheinen sollten um ein Leerzeichen eingerückt.
Selber kam ich auf folgende (zugegebenermaßen etwas umständliche) Lösung:

@in = ;  
$anzahl\_spalten = 3;  
  
for ($x = 0; $x   
Das hilft vielleicht allen weiter, die eine ähnliche Aufgabe zu lösen haben.

Hallo Andy

Selber kam ich auf folgende (zugegebenermaßen etwas
umständliche) Lösung:

@in = ;
$anzahl_spalten = 3;

for ($x = 0; $x

Kann mir schon denken, warum Moritz die
„offensichtliche Lösung“ nicht genannt
hat :wink: (==> PM 742374)

 ...
 use List::MoreUtils ('natatime');
 ...


 ...
 my $it = natatime $anzahl\_spalten, @in;

 while (my @zeile = $it-\>()) {
 print "@zeile\n";
 }
 ...

„von Hand“ würde das so:

...

sub list\_chunk\_iterator {
 my($p, $width, $ar\_ref) = (0, @\_);
 return
 sub {
 my $w = $p;
 $p += $width;
 return $w \> $#$ar\_ref ? () : @$ar\_ref[$w..$w+$width-1]
 }
}

my @in = ;  
**my $p = list\_chunk\_iterator 3, \@in** ;  
while( my @z = $p-\>() ) {  
 print "@z\n"   
}  
...  

aussehen (quick hack, evtl. noch Fehler drin).

Grüße

CMb

Hallo,

Dein Codeschnipsel teilt mir aber leider trotzdem nicht den
Text auf drei Spalten auf, sondern liefert mir die Elemente,
die eigentlich in der zweiten und dritten Spalten erscheinen
sollten um ein Leerzeichen eingerückt.

Huch? Bei welcher Eingabe liefert es dir welche Ausgabe, und was erwartest du?

Grüße,
Moritz

Hallo,

Huch? Bei welcher Eingabe liefert es dir welche Ausgabe, und
was erwartest du?

Was um so verwunderlicher ist, da sogar unter:

 a@b:~/perl\> perl -v
 This is perl, **v5.8.8** built for i586-linux-thread-multi

das reduzierte Programm:

 my @in = ;  
  
 while (my @col = splice @in, 0, 3) {  
 print "@col\n";  
 }  

in diesem Fall das gewünschte Resultat liefert.

Grüße

CMb

Die „say“-Funktion konnte die Ausgabe nicht in meine Ausgabe-Datei schreiben, weshalb ich stattdessen „print“ verwendet habe. Das hat bei der Formatierung aber auch einen Unterschied gemacht.
Mit „say“ funktioniert die Ausgabe auf der Shell einwandfrei.
Könnte mir noch jemand erklären, was an meiner Lösung von Hand die Nachteile sind (abgesehen davon, dass sie länger ist)?

1 Like

hallo andy,

Könnte mir noch jemand erklären, was an meiner Lösung von Hand
die Nachteile sind (abgesehen davon, dass sie länger ist)?

vorallem ist es die lösung, die du haben wolltest :smile:)
(die module geben deinen sortierwunsch nicht her)

habe mal die liste erweitert @in = ( ‚A‘ … ‚Z‘ ) und
festgestellt, dass der letzte eintrag in spalte 1 auch der erste eintrag in spalte 2 ist.

aber mir fällt im moment dazu nichts ein.

gruß
klaus

Hallo,

Die „say“-Funktion konnte die Ausgabe nicht in meine
Ausgabe-Datei schreiben, weshalb ich stattdessen „print“
verwendet habe.

Huch? Das schreiben in Dateien funktioniert mit say() genauso wie mit print() - wenn das bei dir nicht geht, hast du einen bug in Perl entdeckt. Schicke den bitte mit dem Tool ‚perlbug‘ an die Entwickler.

Das hat bei der Formatierung aber auch einen
Unterschied gemacht.

Ja natuerlich. say() macht nicht genau das gleiche wie print(), wenn du also say() durch print() ersetzt, musst du auch selbst ein Zeilenende anhängen.

Grüße,
Moritz