Je suis un débutant dans l'apprentissage de perl.
Ce que j'essaie de faire ici, c'est de diviser le tableau @value
et de l'insérer dans un nouveau tableau. mon problème est que je ne sais pas exactement comment faire fonctionner mon codage en boucle et obtenir le résultat souhaité.
Est-il possible d'obtenir le résultat souhaité en utilisant cette méthode ou existe-t-il une autre alternative / moyen résultat?
Mon code est comme ci-dessous;
my @separated = (); my @separated1 = (); my @separated2 = (); my @separated3 = (); my $counter = 0; my @values = "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD"; foreach (@values) { my @separated = split(' ', $_); push @separated1, $separated[0]; push @separated2, $separated[1]; push @separated3, $separated[2]; } $counter++ print "separated1 = @separated1\n"; print "separated2 = @separated2\n"; print "separated3 = @separated3\n";
Résultat que j'ai obtenu;
séparé1 = aaa
séparé2 = 111
Separated3 = AAA
Résultat souhaité;
séparé1 = aaa bbb ccc ddd
séparé2 = 111222333 444
Separated3 = AAA BB CCC DD
6 Réponses :
my @moos; my @values = split(' ', $input); while (@values) { my %moo; @moo{qw( foo bar qux )} = splice(@values, 0, 3); push @moos, \%moo; }
La première solution mettra des valeurs non définies dans les résultats si le nombre d'éléments dans les $ values
d'origine n'est pas divisible par 3.
@Silvar, c'est intentionnel, il serait donc préférable de souligner que la solution AoA ne fait pas cela.
Une occasion rare où la boucle for de style C est appropriée, pour itérer sur tous les 3 éléments
my @sep = map { [ @values[@$_] ] } part { $_%3 } 0..$#values;
Cela suppose que le tableau a effectivement tous les triplets, ou mieux vérifier chaque élément.
/ p>
Mais il est normalement beaucoup plus agréable de travailler avec une seule structure qu'avec un ensemble de tableaux parallèles. Par exemple, utilisez un tableau avec des éléments qui sont des références de tableau
[ ["aaa", "bbb", "ccc", "ddd"], [111, 222, 333, 444], ["AAA", "BBB", "CCC", "DDD"], ]
où la double itération peut être évitée avec un plus propre
for my $i (0..$#values) { push @{$sep[$i%3]}, $values[$i] }
qui remplace les deux boucles.
Ceci imprime
use Data::Dump qw(dd); my @sep; for (my $i=0; $i <= $#values; $i += 3) { for my $j (0..2) { push @{$sep[$j]}, $values[$i+$j]; } } dd \@sep;
J'utilise Data :: Dump pour voir des données complexes. Une alternative dans le noyau est Data :: Dumper .
Et puis il y a de nombreux modules avec toutes sortes de routines utilitaires pour travailler avec des listes.
Par exemple, en utilisant part de List :: MoreUtils pour partitionner le tableau @values
p>
my $string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD'; my (@sep1, @sep2, @sep3); my @values = split ' ', $string; for (my $i=0; $i <= $#values; $i += 3) { push @sep1, $values[$i]; push @sep2, $values[$i+1]; push @sep3, $values[$i+2]; }
Ceci produit le même @sep
avec arrayrefs que ci-dessus.
La partie
renvoie une liste de arrayrefs, contenant chacun des indices car il partitionnait la liste des indices de @values
. Ensuite, dans map , chaque arrayref est évalué dans sa liste d'indices ( @ $ _
), qui est utilisé pour prendre la tranche correspondante de @values
; cette liste est utilisée pour créer un arrayref avec []
. Ainsi, map
renvoie une liste de arrayrefs, avec des valeurs partitionnées selon les besoins.
Pour travailler avec des références, veuillez consulter le tutoriel perlreftut et référence perlref
Une autre version utilisant part
de la liste non-core mais très utile :: Module MoreUtils , qui partitionne directement les éléments:
sep1: aaa bbb ccc ddd sep2: 111 222 333 444 sep3: AAA BBB CCC DDD
imprime
#!/usr/bin/perl use warnings; use strict; use feature qw/say state/; use List::MoreUtils qw/part/; my $str = "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD"; my ($sep1, $sep2, $sep3) = part { state $i = 0; $i++ % 3 } split(' ', $str); say "sep1: @$sep1"; say "sep2: @$sep2"; say "sep3: @$sep3";
La magie ici est avec state , qui finit par créer une variable locale au bloc dans lequel il se trouve et qui conserve sa valeur plusieurs évaluations du bloc.
Un autre travail pour List :: UtilsBy :
use strict; use warnings; use List::UtilsBy 'bundle_by', 'unzip_by'; my $string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD'; my @vals = split ' ', $string; my ($sep1, $sep2, $sep3) = unzip_by { @$_ } bundle_by { [@_] } 3, @vals; print "sep1: @$sep1\nsep2: @$sep2\nsep3: @$sep3\n";
Cette expression peut vous aider à obtenir les résultats souhaités:
const repeat = 1000000; const start = Date.now(); for (var i = repeat; i >= 0; i--) { const string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD'; const regex = /([a-z]+\s)([0-9]+\s)([A-Z]+)/gm; var match = string.replace(regex, "$1"); } const end = Date.now() - start; console.log("YAAAY! \"" + match + "\" is a match ððð "); console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. ð³ ");
J'aime les solutions de @ikegami et @zdim. @ zdim utilise part ()
de List :: MoreUtils
m'a rappelé natatime
:
my @values = split(' ', "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD"); use List::MoreUtils 'natatime'; my $nata_iter = natatime 3, @values ; my @aoa ; while (my @tmp = $nata_iter->()) { push @aoa, \@tmp; };
Pas vraiment une considération mais peut-être d'intérêt: en utilisant un tableau temporaire ( @tmp
) pour stocker la sortie de l'itérateur, les @values
d'origine restent intactes alors que splice ()
plus simple est destructif.
en fait, vous n'utilisez pas votre variable $ counter. vous l'incrémentez, mais n'y accédez jamais. je suppose que vous vouliez l'utiliser comme index pour vos tableaux.
Cette ligne:
my @values = "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD"
... attribue une valeur scalaire à un tableau. Il met effectivement cette valeur scalaire dans le premier emplacement du tableau@value
. Vous pouvez faire unsplit
ici directement:my @values = split / /, "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD";
Une fois cela en place , le reste est de prendre 3 valeurs à la fois etc etc.