while each hash, why not array

Discussion in 'Perl Misc' started by Robert Wallace, Oct 22, 2003.

  1. I can extract two values at a time from a hash with while, why not with
    an array?

    that is with
    %hashish = ( a => 1, b => 2, c => 3);
    I can:
    while (($k,$v) = each %hashish ){
    print "$k => $v\n";
    }


    why not:
    while (($k,$v) = each @arr){
    print "$k => $v\n";
    }
    Robert Wallace, Oct 22, 2003
    #1
    1. Advertising

  2. Robert Wallace <> wrote in news:3F96D627.BD7B0E36
    @nospam.acm.org:

    > I can extract two values at a time from a hash with while, why not with
    > an array?


    You are extracting one key and one value from the hash.

    > that is with
    > %hashish = ( a => 1, b => 2, c => 3);
    > I can:
    > while (($k,$v) = each %hashish ){
    > print "$k => $v\n";
    > }
    >
    >
    > why not:
    > while (($k,$v) = each @arr){
    > print "$k => $v\n";
    > }


    Because in an array, values are indexed by integers, not by arbitrary
    keys.

    for(my $i = 0; $i != @arr; ++$i) {
    print "$i => $arr[$i]\n";
    }

    Sinan.


    --
    A. Sinan Unur

    Remove dashes for address
    Spam bait: mailto:
    A. Sinan Unur, Oct 22, 2003
    #2
    1. Advertising

  3. Robert Wallace <> wrote:
    > I can extract two values at a time from a hash with while, why not with
    > an array?


    > that is with
    > %hashish = ( a => 1, b => 2, c => 3);
    > I can:
    > while (($k,$v) = each %hashish ){
    > print "$k => $v\n";
    > }



    > why not:
    > while (($k,$v) = each @arr){
    > print "$k => $v\n";
    > }


    Hashes keep the overhead of a counter to note where each should look.
    Arrays do not. If you only need to read through the array once, you
    could just splice them off the front.

    while (($k, $v) = splice(@arr, 0, 2))
    { ... }

    You could shove the data onto another array to keep track of it, but if
    you're going to need the data twice, I'd rather do an index loop
    instead.

    for ($i = 0; $i < @arr ; $i += 2)
    { ($k, $v) = @arr[$i,$i+1];
    ...
    }


    --
    Darren Dunham
    Unix System Administrator Taos - The SysAdmin Company
    Got some Dr Pepper? San Francisco, CA bay area
    < This line left intentionally blank to confuse you. >
    Darren Dunham, Oct 22, 2003
    #3
  4. Robert Wallace wrote:
    >
    > I can extract two values at a time from a hash with while, why not with
    > an array?
    >
    > that is with
    > %hashish = ( a => 1, b => 2, c => 3);
    > I can:
    > while (($k,$v) = each %hashish ){
    > print "$k => $v\n";
    > }


    This is giving you (I think) the key and the value
    for ONE hash entry, NOT two keys or two values.

    > why not:
    > while (($k,$v) = each @arr){
    > print "$k => $v\n";
    > }


    Arrays don't have "keys", so what would you expect
    $k and $v to contain?? If you want an index and a
    value (as the print statement seems to indicate,
    use:

    while ($v = each @arr){
    print "$k => $v\n";
    $k++;
    }

    Mike
    Michael P. Broida, Oct 22, 2003
    #4
  5. Robert Wallace () wrote:
    : I can extract two values at a time from a hash with while, why not with
    : an array?


    : that is with
    : %hashish = ( a => 1, b => 2, c => 3);
    : I can:
    : while (($k,$v) = each %hashish ){
    : print "$k => $v\n";
    : }


    : why not:
    : while (($k,$v) = each @arr){
    : print "$k => $v\n";
    : }

    Because you aren't extracting two "values" at a time from the hash (and
    you're not extracting them using "while" either, though that's just
    pedantics).

    `each' extracts one key and the associated value from a hash.

    each is designed to work on hashes, not arrays.

    If each worked on array's (which would look nice sometimes) then it would
    presumably extract the next, single, value, which is basically what
    foreach does already.

    # hypothetical "each" of array

    while ( $v = each @arr)

    # what you can do today

    foreach my $v (@arr)
    Malcolm Dew-Jones, Oct 22, 2003
    #5
  6. Robert Wallace

    Keith Keller Guest

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    On 2003-10-22, Robert Wallace <> wrote:
    >
    > %hashish = ( a => 1, b => 2, c => 3);
    > while (($k,$v) = each %hashish ){
    > print "$k => $v\n";
    > }
    >
    >
    > # why not:
    > while (($k,$v) = each @arr){
    > print "$k => $v\n";
    > }


    What values do you want assigned to $k and $v in each iteration? I can
    think of two different methods, both of which might make sense depending
    on context.

    1) $k=$arr[0],$v=$arr[1] on first iteration, then $k=$arr[2],$v=$arr[3],
    and so on

    2) $k=0,$v=$arr[0], then $k=1,$v=$arr[1], and so on

    The second is easily accomplished with a rewrite of the loop (I think
    others in the thread have already addressed it). If you mean the first,
    I believe this might work:

    %hash2=@arr; # if @arr has an even number of elements

    If you mean something else you'll need to elaborate: what, exactly, would
    each @arr do?

    - --keith

    - --
    -francisco.ca.us
    (try just my userid to email me)
    AOLSFAQ=http://wombat.san-francisco.ca.us/cgi-bin/fom

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.0.6 (GNU/Linux)
    Comment: For info see http://www.gnupg.org

    iEYEARECAAYFAj+W7o0ACgkQhVcNCxZ5ID+1IACfZCHuK60wIgUbejhMbE7g2gp2
    ANUAnRifh1wwQLCnCf5/vslf+dfuuoxF
    =rEMD
    -----END PGP SIGNATURE-----
    Keith Keller, Oct 22, 2003
    #6
  7. "Michael P. Broida" wrote:
    >
    > while ($v = each @arr){
    > print "$k => $v\n";
    > $k++;
    > }


    Well, my syntax was wrong ("each" with an array),
    but the thought was good. <grin> Change that to:

    $k = 0;
    foreach $v (@arr){
    print "$k => $v\n";
    $k++;
    }

    Mike
    Michael P. Broida, Oct 22, 2003
    #7
  8. A. Sinan Unur <> wrote:

    > for(my $i = 0; $i != @arr; ++$i) {



    Yuck!

    foreach my $i ( 0 .. $#arr ) {


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Oct 22, 2003
    #8
  9. (Tad McClellan) wrote in
    news::

    > A. Sinan Unur <> wrote:
    >
    >> for(my $i = 0; $i != @arr; ++$i) {

    >
    >
    > Yuck!
    >
    > foreach my $i ( 0 .. $#arr ) {


    Agreed. Thanks.

    --
    A. Sinan Unur

    Remove dashes for address
    Spam bait: mailto:
    A. Sinan Unur, Oct 23, 2003
    #9
  10. Robert Wallace

    Anno Siegel Guest

    Abigail <> wrote in comp.lang.perl.misc:
    > Malcolm Dew-Jones () wrote on MMMDCCIV September
    > MCMXCIII in <URL:news:>:
    > {} Robert Wallace () wrote:
    > {} : I can extract two values at a time from a hash with while, why not with
    > {} : an array?
    > {}
    > {}
    > {} : that is with
    > {} : %hashish = ( a => 1, b => 2, c => 3);
    > {} : I can:
    > {} : while (($k,$v) = each %hashish ){
    > {} : print "$k => $v\n";
    > {} : }
    > {}
    > {}
    > {} : why not:
    > {} : while (($k,$v) = each @arr){
    > {} : print "$k => $v\n";
    > {} : }
    > {}
    > {} Because you aren't extracting two "values" at a time from the hash (and
    > {} you're not extracting them using "while" either, though that's just
    > {} pedantics).
    > {}
    > {} `each' extracts one key and the associated value from a hash.
    > {}
    > {} each is designed to work on hashes, not arrays.
    > {}
    > {} If each worked on array's (which would look nice sometimes) then it would
    > {} presumably extract the next, single, value, which is basically what
    > {} foreach does already.
    > {}
    > {} # hypothetical "each" of array
    > {}
    > {} while ( $v = each @arr)
    > {}
    > {} # what you can do today
    > {}
    > {} foreach my $v (@arr)
    >
    >
    > Nah, a hypothetical 'each' for arrays would be:
    >
    > while (my ($key, $value) = each @array) {
    > # $key is the index, $value the value.
    > }


    That would be my idea too of what "each" should mean for an array.
    However, there are other interpretations. Besides Malcolm's (essentially
    equivalent to "foreach"), there was

    while (my ($key, $value) = each @array) {
    # $key is an even-indexed element, $value an odd-indexed element
    }

    which is also a plausible generalization of the behavior of "each",
    though, I believe, not a very useful one.

    Maybe this ambiguity is another reason why "each" hasn't been generalized.

    Anno
    Anno Siegel, Oct 23, 2003
    #10
  11. Robert Wallace

    Greg Bacon Guest

    In article <>,
    Abigail <> wrote:

    : Nah, a hypothetical 'each' for arrays would be:
    :
    : while (my ($key, $value) = each @array) {
    : # $key is the index, $value the value.
    : }

    Sweet! Something like this?

    $ cat ArrayEach.pm
    package ArrayEach;

    use strict;

    require Exporter;
    our @ISA = 'Exporter';
    our @EXPORT = 'each';

    # next index
    my %iter;

    sub each (\[%@]) {
    my $that = shift;

    if (ref($that) eq "HASH") {
    return CORE::each %$that;
    }

    if (defined $iter{$that} && $iter{$that} >= @$that) {
    delete $iter{$that};
    return;
    }

    my $k = $iter{$that}++ || 0;
    my $v = $that->[$k];

    wantarray ? ($k, $v) : $v;
    }

    1;

    $ cat test-each
    #! /usr/local/bin/perl

    use warnings;
    use strict;

    use ArrayEach;

    my %h = (a => 1, b => 2, c => 3);
    my @a = qw/ apples oranges bananas /;

    my %core;
    while (my($k,$v) = CORE::each %h) {
    $core{$k} = $v;
    }

    my %new;
    while (my($k,$v) = each %h) {
    $new{$k} = $v;
    }

    for (keys %core) {
    warn "'$_' missing from new\n"
    unless exists $new{$_} && $new{$_} eq $core{$_};
    }

    for (keys %new) {
    warn "'$_' extra in new\n"
    unless exists $core{$_};
    }

    my @new;
    while (my($k,$v) = each @a) {
    push @new, [$k,$v];
    }

    warn "too many results: ", scalar @new, "\n"
    unless @new == @a;

    for (my $i = 0; $i < @new; ++$i) {
    warn "bad key at $i ($new[$i]->[0])\n"
    unless $i == $new[$i]->[0];

    warn "bad value at $i ($new[$i]->[1])\n"
    unless $a[$i] eq $new[$i]->[1];
    }

    print "Done\n";

    __END__

    Greg
    --
    While the federal government is frustrating when it treats economic
    problems with nonchalance, it is terrifying when it gets involved.
    -- Bob Novak
    Greg Bacon, Oct 23, 2003
    #11
  12. Robert Wallace

    Anno Siegel Guest

    Abigail <> wrote in comp.lang.perl.misc:
    > Anno Siegel (-berlin.de) wrote on MMMDCCV September
    > MCMXCIII in <URL:news:bn8gsj$n8a$-Berlin.DE>:
    > () Abigail <> wrote in comp.lang.perl.misc:
    > () >
    > () >
    > () > Nah, a hypothetical 'each' for arrays would be:
    > () >
    > () > while (my ($key, $value) = each @array) {
    > () > # $key is the index, $value the value.
    > () > }
    > ()
    > () That would be my idea too of what "each" should mean for an array.
    > () However, there are other interpretations. Besides Malcolm's (essentially
    > () equivalent to "foreach"), there was
    > ()
    > () while (my ($key, $value) = each @array) {
    > () # $key is an even-indexed element, $value an odd-indexed element
    > () }
    > ()
    > () which is also a plausible generalization of the behavior of "each",
    > () though, I believe, not a very useful one.
    > ()
    > () Maybe this ambiguity is another reason why "each" hasn't been generalized.
    >
    >
    > My guess the reason 'each' hasn't been generalized is that arrays don't
    > have slots to keep the state of the iterator. Hashes have them. Adding
    > them to arrays means adding an extra integer to all AVs. Considering that
    > 'each @array' will be used far less than 'each %hash', the price is not
    > worth paying.


    Having the iterator incorporated in the hash itself isn't ideal -- it's
    the reason why we can't nest "each"- and "keys"-loops over the same hash.
    One could also take the opportunity and implement both iterators differently.

    Not bloody likely, I know. I wonder how Perl 6 will behave in that respect.

    Anno
    Anno Siegel, Oct 23, 2003
    #12
  13. Robert Wallace

    Anno Siegel Guest

    Abigail <> wrote in comp.lang.perl.misc:
    > Greg Bacon () wrote on MMMDCCV September MCMXCIII in
    > <URL:news:>:
    > `` In article <>,
    > `` Abigail <> wrote:
    > ``
    > `` : Nah, a hypothetical 'each' for arrays would be:
    > `` :
    > `` : while (my ($key, $value) = each @array) {
    > `` : # $key is the index, $value the value.
    > `` : }
    > ``
    > `` Sweet! Something like this?
    >
    > I thought of that myself, but it doesn't work. The problem is that
    > memory addresses aren't unique over time; they are reused:


    One could bless arrays when they are iterated over and take care of
    the %iter entry in DESTROY.

    Besides being absurd, it is fragile. Scratch that :)

    Anno
    Anno Siegel, Oct 23, 2003
    #13
  14. Robert Wallace

    Uri Guttman Guest

    >>>>> "AS" == Anno Siegel <-berlin.de> writes:

    AS> That would be my idea too of what "each" should mean for an array.
    AS> However, there are other interpretations. Besides Malcolm's (essentially
    AS> equivalent to "foreach"), there was

    AS> while (my ($key, $value) = each @array) {
    AS> # $key is an even-indexed element, $value an odd-indexed element
    AS> }

    AS> which is also a plausible generalization of the behavior of "each",
    AS> though, I believe, not a very useful one.

    perl6 has that in the form of the un/zip function (it merges/splits
    lists).

    and it is useful when you have a set of pairs (maybe config stuff) that
    needs to be processed in order. getting the next N elements into a list
    of scalars (perl6 can do wierd combos of this as well) is a highly
    desired function.

    AS> Maybe this ambiguity is another reason why "each" hasn't been generalized.

    well delete was changed to support (the soon to be dead)
    pseudo-hashes. each could have been generalized to return the
    index/value pair which is not a bad idea but i doubt i ever would need
    it. it would be exteremely rare to find index driven code in any of my
    source.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Oct 23, 2003
    #14
  15. Anno Siegel (-berlin.de) wrote:
    : Abigail <> wrote in comp.lang.perl.misc:
    : > Anno Siegel (-berlin.de) wrote on MMMDCCV September
    : > MCMXCIII in <URL:news:bn8gsj$n8a$-Berlin.DE>:
    : > () Abigail <> wrote in comp.lang.perl.misc:
    : > () >
    : > () >
    : > () > Nah, a hypothetical 'each' for arrays would be:
    : > () >
    : > () > while (my ($key, $value) = each @array) {
    : > () > # $key is the index, $value the value.
    : > () > }
    : > ()
    : > () That would be my idea too of what "each" should mean for an array.
    : > () However, there are other interpretations. Besides Malcolm's (essentially
    : > () equivalent to "foreach"), there was
    : > ()
    : > () while (my ($key, $value) = each @array) {
    : > () # $key is an even-indexed element, $value an odd-indexed element
    : > () }
    : > ()
    : > () which is also a plausible generalization of the behavior of "each",
    : > () though, I believe, not a very useful one.
    : > ()
    : > () Maybe this ambiguity is another reason why "each" hasn't been generalized.
    : >
    : >
    : > My guess the reason 'each' hasn't been generalized is that arrays don't
    : > have slots to keep the state of the iterator. Hashes have them. Adding
    : > them to arrays means adding an extra integer to all AVs. Considering that
    : > 'each @array' will be used far less than 'each %hash', the price is not
    : > worth paying.

    : Having the iterator incorporated in the hash itself isn't ideal -- it's
    : the reason why we can't nest "each"- and "keys"-loops over the same hash.
    : One could also take the opportunity and implement both iterators differently.

    : Not bloody likely, I know. I wonder how Perl 6 will behave in that respect.

    perl 6, no idea, but the way other languages handle it would be to create
    an iteration object, so you could imagine

    my $iter1 = iterator_for %hash;

    while ( my ($k,$v) = $iter->next ) or such like

    OR
    store a context handle or other identifier as an optional argument to the
    each

    while ( my ($k,$v) = each(%hash,$iter1) )
    Malcolm Dew-Jones, Oct 23, 2003
    #15
  16. Robert Wallace

    Greg Bacon Guest

    In article <bn8phl$152$-Berlin.DE>,
    Anno Siegel <-berlin.de> wrote:

    : [...]
    : Not bloody likely, I know. I wonder how Perl 6 will behave in that
    : respect.

    Thus sayeth Exegesis 6:

    . . . Instead, we have to consider both the index and the value of
    each data element.

    To do that we use the @data array's .kv method. Just as calling
    the .kv method on a hash returns key, value, key, value, key,
    value, etc., so too calling the .kv method on an array returns
    index, value, index, value, index, value, etc. Then we just use a
    parameterized block as our for block, specifying that it has two
    arguments. That causes the for to grab two elements of the list
    its iterating (i.e. one index and one value) on each iteration.

    Then we simply test to see if the current index is any of those
    specified in $is_sheep's array and, if so, we push the
    corresponding value:

    for @data.kv -> $index, $value {
    if $index == any(@$is_sheep) { push %herd{$sheep}, $value }
    else { push %herd{$goats}, $value }
    }

    See http://www.perl.com/pub/a/2003/07/29/exegesis6.html?page=8

    Greg
    --
    Procrastinators, of which I'm one of the worst, are routinely cruel to
    their future selves.
    -- Charley Hardman
    Greg Bacon, Oct 25, 2003
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,756
    Smokey Grindel
    Dec 2, 2006
  2. rp
    Replies:
    1
    Views:
    494
    red floyd
    Nov 10, 2011
  3. Srijayanth Sridhar
    Replies:
    19
    Views:
    596
    David A. Black
    Jul 2, 2008
  4. Patrick Doyle

    Hash#each vs Hash#each_pair

    Patrick Doyle, Aug 18, 2008, in forum: Ruby
    Replies:
    11
    Views:
    228
    Michael Fellinger
    Aug 18, 2008
  5. Igor Nn
    Replies:
    7
    Views:
    426
    Johnny Morrice
    May 28, 2011
Loading...

Share This Page