string in blöcke aufteilen
frank
- perl
0 opi0 Norbert Klein0 opi0 Norbert Klein0 opi0 Benne0 frank0 Norbert Klein
hallo,
ich muss einen string variabler länge in perl in blöcke fester länge aufteilen.
habe also z.b. einen string:
$string="123456789asdgfbbnf";
dieser soll aufgeteilt werden in z.b. blöcke der länge 4, so dass am ende ein array mit allen blöcken entsteht. das letzte element des arrays muss also nicht zwanglaeufig (so wie in diesem beispiel) auch eine laenge von 4 haben.
es gibt keine festen trennzeichen, einzig die laenge soll als trennparameter dienen.
habe es schon mit
@bloecke=split /(.{4})/,$string;
probiert, aber das liefert auch leere elemente zurueck.
auch
@bloecke=();
$string=~s/(.{4})/push(@bloecke,$1)/ge;
liefert nicht das gewuenschte ergebnis, da dann das letzte element fehlt, wenn es nicht genau die laenge 4 hat.
man koennte natuerlich vorher die laenge des strings ermitteln und dann so oft teile aus dem string lesen (und diesen kuerzen), wie es sich eben durch 4 teilen laesst, aber das muss doch auch einfacher gehen.
vielleicht kann mir jemand helfen
Hallo Frank,
habe es schon mit
@bloecke=split /(.{4})/,$string;
probiert, aber das liefert auch leere elemente zurueck.
nun weil Leerzeichen auch Zeichen.
Wie wäre es hiermit:
# deinem split Beispiel
foreach ( split /(.{4})/, $string ) {
next if /^\s+$/;
s/^\s+//;
s/\s+$//;
push @bloecke;
}
# oder mit substr
my $len = length($string)/4;
for (my $i = 0 ; $len < $i ; $i += 4) {
push @bloecke, substr($string,$i,4);
}
Die substr Variante habe ich nicht getestet, aber der Ansatz sollte
stimmen.
Greez,
opi
Hallo Frank,
entschuldige, aber mein substr Beispiel enthielt einige Fehler!
Dieses Beispiel hier habe ich gerade ausprobiert und es funktioniert
fabelhaft :-)
#!/usr/bin/perl
use strict;
use warnings;
my $string = "123456789012 ww "; # ww zum Testen der entfernten Leerzeichen
my $bloecke = [];
my $laenge = length($string);
for (my $i = 0 ; $laenge > $i ; $i += 4) {
my $val = substr($string,$i,4);
$val =~ s/^\s+//;
$val =~ s/\s+$//;
push @$bloecke, $val;
}
foreach (@$bloecke) {
print "<$_>\n";
}
Greez,
opi
Hallo opi,
my $string = "123456789012 ww "; # ww zum Testen der entfernten Leerzeichen
my $bloecke = [];
my $laenge = length($string);
for (my $i = 0 ; $laenge > $i ; $i += 4) {
my $val = substr($string,$i,4);
$val =~ s/^\s+//;
$val =~ s/\s+$//;
push @$bloecke, $val;
}
foreach (@$bloecke) {
print "<$_>\n";
}
ich weiß zwar nich, was du da für komische Handstände und Flickflacks machst, aber effizienter geht es z.B. so:
~~~perl
#!/usr/bin/perl -T
use strict;
use warnings;
my $string = "123456789012 ww ";
# String in 4er Zeichenblöcke ohne Leerzeichen zerlegen
my @bloecke = grep { /^\S+$/ } split /(\S{1,4})/, $string;
# Ausgabe
print join ", ", @bloecke;
print "\n";
Gruß,
Benne
Hallo Benne,
ich weiß zwar nich, was du da für komische Handstände und Flickflacks machst
dafür habe ich meinen Grund.
aber effizienter geht es z.B. so:
Falsch. Wenn du schon von Effizient sprichst ...
Benchmark::cmpthese(-1, {
'substr' => sub { for (my $i = 0 ; $laenge > $i ; $i += 4) {
my $val = substr($string,$i,4);
next if $val =~ /^(\s+|)$/;
push @$bloecke, $val;
}
},
'split' => sub { @$bloecke = grep { /^\S+$/ } split /(\S{1,4})/, $string; }
});
Rate split substr
split 9135/s -- -55%
substr 20210/s 121% --
substr ist doppelt so schnell.
Greez,
opi
Hallo opi,
aber effizienter geht es z.B. so:
Falsch. Wenn du schon von Effizient sprichst ...
Benchmark::cmpthese(-1, {
'substr' => sub { for (my $i = 0 ; $laenge > $i ; $i += 4) {
my $val = substr($string,$i,4);
next if $val =~ /^(\s+|)$/;
push @$bloecke, $val;
}
},
'split' => sub { @$bloecke = grep { /^\S+$/ } split /(\S{1,4})/, $string; }
});
ich spreche nicht von Performanz.
Ausschnitt aus <http://de.wikipedia.org/wiki/Effizient>:
...ist das Verhältnis eines in definierter Qualität vorgegebenen Nutzens zu dem Aufwand, der zur Erreichung des Nutzens nötig ist.
...In der Informatik meint man mit Effizienz entweder die Leistung des implementierten Algorithmus oder Komplexität (bei Algorithmen)
Man kann vielleicht eine längere Debatte führen, welche Methode komplexer ist.
Meine Meinung ist, dass die generelle Verwendung von grep/split "perlisher" und übersichtlicher ist.
Gruß,
Benne
--
ie:% fl:( br:> va:) ls:> fo:| rl:° ss:) de:[ js:| ch:| mo:} zu:)
Hallo Benne,
Man kann vielleicht eine längere Debatte führen, welche Methode komplexer ist.
Meine Meinung ist, dass die generelle Verwendung von grep/split "perlisher" und übersichtlicher ist.
meinst du mit "perlisher" weil du schön alles in eine Zeile packst?
Ich finde mein Beispiel weder komplex noch unübersichtlich.
...In der Informatik meint man mit Effizienz entweder die Leistung des implementierten Algorithmus oder Komplexität (bei Algorithmen)
Performanz ist doch Leistung.
Die Leistung von substr ist mehr als das doppelte.
Greez,
opi
Hallo frank,
dein Ansatz mit
@bloecke=split /(.{4})/,$string;
ist doch schon sehr gut. Die leeren Elemente kannst du ganz einfach mit grep raus werfen:
my @bloecke = grep {$_ ne ""} split(/(.{4})/,$string);
Mehr Informationen zu grep: perldoc -f grep
Schöne Grüße,
Norbert Klein
Hallo Nobert,
my @bloecke = grep {$_ ne ""} split(/(.{4})/,$string);
Der String könnte aber auch wie folgt ausschauen:
" "
" "
" "
" "
substr wäre zudem ein wenig schneller :-)
Greez,
opi
Hallo.
my @bloecke = grep {$_ ne ""} split(/(.{4})/,$string);
Der String könnte aber auch wie folgt ausschauen:
" "
" "
" "
" "
Und?
Du weißt aber, dass mit leeren Elementen ("") was anderes gemeint ist, als mit Leerzeichen (" "), ja?
Schöne Grüße,
Norbert Klein
Hallo,
my @bloecke = grep {$_ ne ""} split(/(.{4})/,$string);
Du weißt aber, dass mit leeren Elementen ("") was anderes gemeint ist, als mit Leerzeichen (" "), ja?
Wenn du Elemente mit nur Leerzeichen haben möchtest... ok.
Und falls $string leer sein sollte, dann verarbeitest du den String
doch sicherlich nicht.
Greez,
opi
Hallo
Du weißt aber, dass mit leeren Elementen ("") was anderes gemeint ist, als mit Leerzeichen (" "), ja?
leider hat frank nicht genau definiert, was er meint. So können wir hier nur raten. Schade eigentlich.
Gruß,
Benne
also, ich meinte tatsaechlich leere elemente.
leerzeichen im string sind nicht das problem, da ich diese auch in den bloecken haben muss. wie bereits gesagt, ist der inhalt des urspruenglichen strings vollkommen egal (also auch leerzeichen).
das problem beim split ist, dass es ja "paarweise" ergebnisse liefert. falls der split also nur einen treffer hat (und der string genauso lang ist wie die blocklaenge), liefert er zwei ergebniselemente und eines ist eben leer. gleiches gilt fuer strings mit vielfachen der blocklaenge.
ich muss auf diese art zwei strings unbekannten inhalts und unbekannter laenge blockweise vergleichen und da ist es nicht so toll, wenn ich leere elemente einfach ignoriere bzw. rauswerfe.
die momentan beste loesung scheint mir die substr methode zu sein. ist auch relativ schnell.
vielen dank
Hallo Benne.
leider hat frank nicht genau definiert, was er meint. So können wir hier nur raten. Schade eigentlich.
Wenn man mit split eine Zeichenkette auseinander nimmt, und die Trennzeichen mitnehmen möchte, macht man das bekanntlich so:
my @array = split(/(TRENNZEICHEN)/,$string);
Das Ergebnis wären folglich die Trennzeichen, sowie all die Teile der Zeichenkette, die keine Trennzeichen sind. Beispiel:
my $string = 'The quick brown fox jumps over the lazy dog.';
my @array = split(/(\W)/,$string);
print "'".join("'\n'",@array)."'";
Die Ausgabe würde wie folgt aussehen:
'The'
' '
'quick'
' '
'brown'
' '
'fox'
' '
'jumps'
' '
'over'
' '
'the'
' '
'lazy'
' '
'dog'
'.'
Wenn die Zeichenkette allerdings nur aus Trennzeichen besteht, wie in dem Fall, den frank beschrieben hat, sieht das Ganze so aus:
my $string = 'The quick brown fox jumps over the lazy dog.';
my @array = split(/(\w+\W)/,$string);
print "'".join("'\n'",@array)."'";
Die Ausgabe wäre hierbei:
''
'The '
''
'quick '
''
'brown '
''
'fox '
''
'jumps '
''
'over '
''
'the '
''
'lazy '
''
'dog.'
Und wie wir sehen, entstehen dabei sehr viele leere Elemente, da sich zwischen den Trennzeichen nunmal keine weiteren Zeichen befinden. Und um eben diese leeren Elemente geht es.
Benutzt man dann grep, um die leeren Elemente zu entfernen...
my $string = 'The quick brown fox jumps over the lazy dog.';
my @array = grep {$_ ne ""} split(/(\w+\W)/,$string);
print "'".join("'\n'",@array)."'";
erhält man die gewünschte Ausgabe:
'The '
'quick '
'brown '
'fox '
'jumps '
'over '
'the '
'lazy '
'dog.'
Und ich vermute, dass frank mit den leeren Elementen genau das gemeint hat.
Schöne Grüße,
Norbert Klein