Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

can we pass two variable to foreach loop

by phemal (Sexton)
on Mar 28, 2007 at 05:35 UTC ( #606912=perlquestion: print w/replies, xml ) Need Help??
phemal has asked for the wisdom of the Perl Monks concerning the following question:

can we pass two variable to foreach loop
foreach my ($x,$y) ($name,$lastname) { do something }

Replies are listed 'Best First'.
Re: can we pass two variable to foreach loop
by BrowserUk (Pope) on Mar 28, 2007 at 05:43 UTC

    No. Not in perl 5. But you could do

    foreach my $ref ( [ $name, $lastname ] ) { my( $x, $y ) = @$ref; # do something }

    Whether that is applicable to your problem would require more context. Where do the values you which to index in pairs come from?

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      what does @$listname stand for?
Re: can we pass two variable to foreach loop
by grinder (Bishop) on Mar 28, 2007 at 06:36 UTC

    Taking n elements of an array at a time is about the only truly useful purpose to which a C-style for loop in Perl may be put. That said, beware of the last iteration of the loop. If the number of elements in the list divided by the number taken each turn leaves a remainder, the last iteration will come up short and you'll have to test whether the element pointed to by the index is defined or not. For instance 5 elements taken 2 at a time gives 1 element left over in the last time through the loop.

    On the other hand, if you don't mind emptying out the array by removing the n elements at a time, then splice will work as well, and as an added bonus, if the final iteration comes up short, splice will simply return fewer elements. If you use them as an array you're fine. Then again, if you need to distinguish them individually, you'll have to test how many splice gave you.

    use strict; use warnings; my @arr = ('a' .. 'z', 'Z'); # non-destructively for (my $i = 0; $i < @arr; $i += 2) { print "$arr[$i] $arr[$i+1]\n"; } # destructively while (my @pair = splice(@arr, 0, 2)) { print "@pair\n"; }

    • another intruder with the mooring in the heart of the Perl

Re: can we pass two variable to foreach loop
by bobf (Monsignor) on Mar 28, 2007 at 05:45 UTC

    No, but you can use a list of references to hashes or arrays that contain multiple values:

    my @AoH = ( { firstname => 'foo', lastname => 'bar' }, { firstname => 'baz', lastname => 'quux' } ); foreach my $href ( @AoH ) { # do something with $href->{firstname} and $href->{lastname} }

Re: can we pass two variable to foreach loop
by Zaxo (Archbishop) on Mar 28, 2007 at 05:57 UTC

    Not exactly. You can set up that kind of thing with Perl's C-style for loop. Perl style for like you show takes single element at a time from a list.

    If you can get several hunks of data into each element of the list, you can define ($x,$y) inside the loop and extract the data:

    for ([qw/Joe Blow/], [qw/John Doe/]) { my ($x, $y) = @$_; # do something }
    for ('Joe Blow', 'John Doe') { my ($x, $y) = split; # and so on }

    The for loop in your example could be written:

    { my ($x, $y) = ($name, $lastname); # do something }

    C-style for can get very baroque, but that's not encouraged, even in C.

    After Compline,

Re: can we pass two variable to foreach loop
by ferreira (Chaplain) on Mar 28, 2007 at 10:18 UTC
    Adding to the suggestions by BrowserUk, Zaxo and grinder, another possible solution would be to use each_array from List::MoreUtils. It is a bit of overkill for your current case, but it would work well if you generalized your problem to:
    foreach my ($x,$y) (@name,@lastname) { do something }
    Only that it would be written as:
    use List::MoreUtils qw(each_array); ... my $names = each_array(@name, @lastname); while ( my ($x, $y) = $names->() ) { do something }
    With each_array, you may create an iterator which is able to loop over more than one array at once. That easy.
Re: can we pass two variable to foreach loop
by ambrus (Abbot) on Mar 28, 2007 at 18:26 UTC

    What would you want it to do?

    1. Iterate on two arrays in paralel:
      @name = qw(fred wilma barney betty); @color = qw(black red blonde black); for $k (0 .. @name - 1) { print $name[$k] . " - " . $color[$k] . "\n" +} # fred - black # wilma - red # barney - blonde # betty - black
    2. Move a sliding window on an array:
      @name = qw(fred wilma barney betty); for $k (0 .. @name - 2) { print $name[$k] . " - " . $name[$k + 1] . "\ +n" } # fred - wilma # wilma - barney # barney - betty
    3. Take the elements of the array in twos:
      @name = qw(fred wilma barney betty); for $k (0 .. @name/2 - 1) { print $name[2 * $k] . " - " . $name[2 * $k + + 1] . "\n" } # fred - wilma # barney - betty
    4. Iterate on an array of pairs:
      @data = (["fred", "black"], ["wilma", "red"], ["barney", "blonde"], [" +betty", "black"]); @color = qw(black red blonde black); for $rec (@data) { my($name, $col +or) = @$rec; print $name . " - " . $color . "\n" } # fred - black # wilma - red # barney - blonde # betty - black
    Or perhaps even something you would normally do with two levels of loops, like iterating on each combination of two names.
Re: can we pass two variable to foreach loop
by Sidhekin (Priest) on Mar 28, 2007 at 05:42 UTC

    Not until Perl 6.

    Meanwhile, there are still other ways to do it. Any specific use case in mind?

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: can we pass two variable to foreach loop
by glenn (Scribe) on Oct 05, 2015 at 15:16 UTC

    Made an amalgamation of two of the suggestions plus added a condition which is what I needed. Hope you find it useful. Basically my systems always have a left IP some have a peer system.

    for (["Left",$system->{ip}->[0]], (["Right",$system->{peer}->[0]->{ip} +->[0]])x!!(exists $system->{peer})) { my ($side, $ip) = @$_; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://606912]
Approved by BrowserUk
[davido]: Exactly: SoPW. This isn't going to be solved easily in the CB.
[james28909]: in need "yesterday" and so on, to be absolute like "1" or "31"
[stevieb]: ...and throw some of your existing code into the equation as well, just so readers know you've given a try at it ;)
[james28909]: ok
[stevieb]: davido thanks for the link ;) I was being the typical lazy
[davido]: date parsing is hard. The more examples you can provide of the input (within reason) and expected output, the better.
[stevieb]: agreed. That's why I said at least a half-dozen. If enough of the different formats are present, the date/time folk may not have to request more. If they do, then at least there was a decent base to start with
[stevieb]: I do date and time transformations in both Perl and Python, but not frequently enough to not have to search for the format params etc ;)

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2017-04-29 02:40 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (531 votes). Check out past polls.