Help with a bad bug: why is my original array being altered??

Discussion in 'Perl Misc' started by Alf McLaughlin, Mar 17, 2006.

  1. Hello all-
    Please look at the code at the code listed below. It produces the
    result also listed below. My question is, I have absolutely no idea
    why the values in my original array are changing when I perform
    operations on the second array. I am totally stumped... I do not
    understand why the @match array seems to share the same memory address
    as @array. Any help is much appreciated!

    Thanks, Alf

    THE RESULT:

    In match array:
    ===============
    70 c
    75 d
    77 e
    88 f
    In original array:
    ==================
    4 a
    6 b
    700000 c
    750000 d
    770000 e
    880000 f
    99 g
    100 h
    105 i
    200 j
    300 k

    THE CODE:

    #!/usr/bin/perl

    MAIN: {
    my $ra_array = get_array();
    my $low_range = 68;
    my $high_range = 90;
    my @match = grep {my $i = $_; $i->[0] >= $low_range and $i->[0] <=
    $high_range} @$ra_array;
    print "In match array:\n";
    print "===============\n";
    foreach my $i (@match) {
    print "$i->[0]\t$i->[1]\n";
    $i->[0] *= 10000;
    }
    print "In original array:\n";
    print "==================\n";
    foreach my $i (@$ra_array) {
    print "$i->[0]\t$i->[1]\n";
    }
    }

    sub get_array {
    my @array; #= (4, 6, 70, 75, 77, 88, 99, 100, 105, 200, 300);
    $array[0] = [(4, 'a')];
    $array[1] = [(6, 'b')];
    $array[2] = [(70, 'c')];
    $array[3] = [(75, 'd')];
    $array[4] = [(77, 'e')];
    $array[5] = [(88, 'f')];
    $array[6] = [(99, 'g')];
    $array[7] = [(100, 'h')];
    $array[8] = [(105, 'i')];
    $array[9] = [(200, 'j')];
    $array[10] =[(300, 'k')];
    return \@array;
    }
     
    Alf McLaughlin, Mar 17, 2006
    #1
    1. Advertising

  2. Alf McLaughlin

    Guest

    Alf McLaughlin wrote:
    > Hello all-
    > Please look at the code at the code listed below. It produces the
    > result also listed below. My question is, I have absolutely no idea
    > why the values in my original array are changing when I perform
    > operations on the second array. I am totally stumped... I do not
    > understand why the @match array seems to share the same memory address
    > as @array. Any help is much appreciated!
    >
    > Thanks, Alf
    >
    > THE RESULT:
    >
    > In match array:
    > ===============
    > 70 c
    > 75 d
    > 77 e
    > 88 f
    > In original array:
    > ==================
    > 4 a
    > 6 b
    > 700000 c
    > 750000 d
    > 770000 e
    > 880000 f
    > 99 g
    > 100 h
    > 105 i
    > 200 j
    > 300 k
    >
    > THE CODE:
    >
    > #!/usr/bin/perl
    >
    > MAIN: {
    > my $ra_array = get_array();
    > my $low_range = 68;
    > my $high_range = 90;
    > my @match = grep {my $i = $_; $i->[0] >= $low_range and $i->[0] <=
    > $high_range} @$ra_array;
    > print "In match array:\n";
    > print "===============\n";
    > foreach my $i (@match) {
    > print "$i->[0]\t$i->[1]\n";
    > $i->[0] *= 10000;


    aren't you multiplying your array content here by 10,000?

    > }
    > print "In original array:\n";
    > print "==================\n";
    > foreach my $i (@$ra_array) {
    > print "$i->[0]\t$i->[1]\n";
    > }
    > }
    >
     
    , Mar 17, 2006
    #2
    1. Advertising

  3. Alf McLaughlin

    Uri Guttman Guest

    >>>>> "AM" == Alf McLaughlin <> writes:

    AM> Please look at the code at the code listed below. It produces the
    AM> result also listed below. My question is, I have absolutely no idea
    AM> why the values in my original array are changing when I perform
    AM> operations on the second array. I am totally stumped... I do not
    AM> understand why the @match array seems to share the same memory address
    AM> as @array. Any help is much appreciated!

    AM> MAIN: {
    AM> my $ra_array = get_array();
    AM> my @match = grep {my $i = $_; $i->[0] >= $low_range and $i->[0] <=
    AM> $high_range} @$ra_array;

    that copies the array refs in the input array. they are the same anon
    arrays as in the input. you did a shallow copy (filtered by grep). you
    need to loop over each of those and make a deeper copy. if you know that
    you will have just that data structure a map will do a proper deep copy
    (untested):

    my @copies = map [ @{$_} ], @match ;

    now if you modify anything in @copies it won't touch the original
    anon arrays in @match. you can combine that map with the grep if you
    want.

    AM> print "In match array:\n";
    AM> print "===============\n";
    AM> foreach my $i (@match) {
    AM> print "$i->[0]\t$i->[1]\n";
    AM> $i->[0] *= 10000;
    AM> }

    use some white space and better formatting.
    AM> sub get_array {

    if the array is fixed why regenerate it each time in this code?

    AM> my @array; #= (4, 6, 70, 75, 77, 88, 99, 100, 105, 200, 300);
    AM> $array[0] = [(4, 'a')];
    AM> $array[1] = [(6, 'b')];
    AM> $array[2] = [(70, 'c')];

    ewww, i hate seeing repetitive code like that. just assign the anon
    arrays in a single list:

    my @array = (
    [(4, 'a')],
    [(6, 'b')],
    ) ;

    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, Mar 17, 2006
    #3
  4. Alf McLaughlin wrote:
    > Please look at the code at the code listed below. It produces the
    > result also listed below. My question is, I have absolutely no idea
    > why the values in my original array are changing when I perform
    > operations on the second array. I am totally stumped... I do not
    > understand why the @match array seems to share the same memory address
    > as @array.


    It does not. The elements of @match are independant of those of @array.
    But the elements of @array are refereneces to things (anonymous arrays
    as it happens) and the elements of @match are references to the very
    same things.

    So in the code below $match[0] is not the same thing as $array[2] it
    just happens to have the same value. But consequently $match[0][0] is
    the same thing as $array[2][0].

    > MAIN: {
    > my $ra_array = get_array();
    > my $low_range = 68;
    > my $high_range = 90;
    > my @match = grep {my $i = $_; $i->[0] >= $low_range and $i->[0] <=
    > $high_range} @$ra_array;
    > print "In match array:\n";
    > print "===============\n";
    > foreach my $i (@match) {
    > print "$i->[0]\t$i->[1]\n";
    > $i->[0] *= 10000;
    > }
    > print "In original array:\n";
    > print "==================\n";
    > foreach my $i (@$ra_array) {
    > print "$i->[0]\t$i->[1]\n";
    > }
    > }
    >
    > sub get_array {
    > my @array; #= (4, 6, 70, 75, 77, 88, 99, 100, 105, 200, 300);
    > $array[0] = [(4, 'a')];
    > $array[1] = [(6, 'b')];
    > $array[2] = [(70, 'c')];
    > $array[3] = [(75, 'd')];
    > $array[4] = [(77, 'e')];
    > $array[5] = [(88, 'f')];
    > $array[6] = [(99, 'g')];
    > $array[7] = [(100, 'h')];
    > $array[8] = [(105, 'i')];
    > $array[9] = [(200, 'j')];
    > $array[10] =[(300, 'k')];
    > return \@array;
    > }
     
    Brian McCauley, Mar 17, 2006
    #4
  5. >my @copies = map [ @{$_} ], @match ;

    Thanks, that's just what I needed; your explanation makes sense.

    >if the array is fixed why regenerate it each time in this code?


    Just for an example (the real array in my actual program comes from
    something else).

    >ewww, i hate seeing repetitive code like that. just assign the anon
    >arrays in a single list:


    Sure, that works too. Again, I usually automate array generation :)
     
    Alf McLaughlin, Mar 17, 2006
    #5
  6. Alf McLaughlin

    Guest

    "Alf McLaughlin" <> wrote:
    > Hello all-
    > Please look at the code at the code listed below. It produces the
    > result also listed below. My question is, I have absolutely no idea
    > why the values in my original array are changing when I perform
    > operations on the second array.


    Your original arrays contains references to other two-element arrays.
    The values (i.e. references) in your original array are not changing. It
    is the values in the small arrays being referenced by the values in the
    original array that are changing.


    > I am totally stumped... I do not
    > understand why the @match array seems to share the same memory address
    > as @array. Any help is much appreciated!


    That is how references work. Either make a deep(er) copy of the small
    arrays, or simply don't change them.

    @match = map [@$_], grep {...} @$ra_array;

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Mar 17, 2006
    #6
  7. Glenn Jackman, Mar 17, 2006
    #7
    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. Christian Döring

    Can the Profile data be altered by the client?

    Christian Döring, Apr 20, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    303
    Christian Döring
    Apr 20, 2006
  2. Henry van der Beek

    Perform operation whenever dir is altered

    Henry van der Beek, Jul 5, 2004, in forum: Python
    Replies:
    1
    Views:
    461
    John Lenton
    Jul 5, 2004
  3. Tim Golden
    Replies:
    0
    Views:
    407
    Tim Golden
    Jul 5, 2004
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,999
    Smokey Grindel
    Dec 2, 2006
  5. rantingrick
    Replies:
    44
    Views:
    1,226
    Peter Pearson
    Jul 13, 2010
Loading...

Share This Page