7 votes

Quelle est la meilleure façon en Perl d'itérer une boucle et d'en extraire des paires ou des triplets ?

J'ai un tableau plat de coordonnées et je veux itérer et extraire des paires de coordonnées x et y. La même logique pourrait s'appliquer aux triples pour les couleurs RVB. C'est ce que j'ai fait jusqu'à présent, mais ce n'est pas très flexible ni élégant.

my @coords = qw(1 5 2 6 3 8 6 12 7 5);

for (my $i = 0; $i < @coords; $i += 2) {
    my $x = $coords[$i];
    my $y = $coords[$i+1];

    print "$x, $y\n";
}

Il doit y avoir un meilleur moyen de faire ça, non ?

6voto

zdim Points 29788

Le module Liste::MoreUtils tiene natatime (n-à-un-temps)

use List::MoreUtils qw(natatime);

my @ary = 1..12; 

my $it = natatime 3, @ary;  # iterator

while (my @triplet = $it->()) { say "@triplet" }

4voto

mob Points 61524

splice est un meilleur moyen

while (my ($x,$y) = splice @coords, 0, 2) {
    ...
}

Deux choses à noter.

  1. splice consomme les éléments de @coords . Si vous ne voulez pas que votre boucle détruise le contenu de votre tableau, utilisez un tableau temporaire.

       my @tmp = @coords;
       while (my ($x,$y) = splice @tmp,0,2) { ... }
  2. Si l'entrée ne contient pas un nombre pair d'éléments, vous pouvez ajouter une vérification supplémentaire pour vous assurer que chaque itération a accès au bon nombre d'éléments.

       while (2 == (my ($x,$y) = splice @coords,0,2)) { ... }

4voto

Andy A. Points 735

Vous pouvez utiliser shift dans un while boucle.

#!/usr/bin/perl

my @coords = qw/1 5 2 6 3 8 6 12 7 5/;
my ($x, $y);

while (@coords) {
    $x = shift @coords;
    $y = shift @coords;
    # another shift to get triples

    # Do something with $x, $y, ...
    say "$x, $y";
}

La boucle while s'exécute jusqu'à ce que @coords est vide. shift récupère le premier élément et le supprime du tableau.

Évitez undef en donnant une valeur par défaut :

Si vous essayez ci-dessus avec des triples, vous obtiendrez une erreur car il y aura des valeurs non définies dans la dernière exécution. $x sera 5 et ensuite @coords est vide.

Donnez donc une valeur par défaut en utilisant // .

#!/usr/bin/perl

my @coords = qw/1 5 2 6 3 8 6 12 7 5/;
my ($x, $y, $z);

while (@coords) {
    $x = shift @coords; # is defined!
    $y = shift @coords // "<undef>";
    $z = shift @coords // "<undef>";

    # ...
}

N'utilisez pas || ! Parce que shift @coords || "<undef>"; sera "<undef>" si la valeur actuelle est évaluée à false ( 0 , "" , ...).

3voto

Shawn Points 13289

Vous pouvez utiliser pairs du cœur List::Util pour transformer une liste de nombres pairs d'éléments en une liste de refs de tableaux à deux éléments :

#!/usr/bin/env perl
use warnings;
use strict;
use List::Util qw/pairs/;

my @coords = qw(1 5 2 6 3 8 6 12 7 5);

for my $pair (pairs @coords) {
    my ($x, $y) = @$pair;
    # ...
}

3voto

Polar Bear Points 4537

Une approche du problème à l'ancienne

use strict;
use warnings;
use feature 'say';

my @coords = qw(1 5 2 6 3 8 6 12 7 5);
my($x,$y);

while( ($x,$y,@coords) = @coords ) {
    say "$x, $y";
}

Sortie

1, 5
2, 6
3, 8
6, 12
7, 5

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X