Removing entry from @rray

Discussion in 'Perl Misc' started by Robert Valcourt, Dec 11, 2006.

  1. Hello,

    For some time I have been using two different method for removing an entry
    from an @rray. It is my beleif that these methods may be outdated or
    erroneous and I wanted to get some opinions. My program reads the contents
    of a text file, and places each line into the array. Here are my two
    methods:

    Using Splicing
    =========================

    open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    @entries=<ADDRESSES>;
    close(ADDRESSES);

    $variable = "Smith";

    foreach $entry(@entries) {
    $location++;
    if ($entry eq $variable) {
    $location--;
    $line = $location;
    }
    }

    splice(@entries, $line, 1);

    First of all I understand that many of you will first comment on the means
    by which I read the text file and place its content into the array or that
    strict isnt used above, and I will be fixing that soon using SLURP and
    calling the "use strict" header.

    So this method uses the old splice routine. I find this method to be
    confusing and im not quite a fan of it. On to the next:

    Redefining the @array element inside to loop
    =========================

    open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    @entries=<ADDRESSES>;
    close(ADDRESSES);

    $variable = "Smith";

    foreach $entry(@entries) {
    if ($entry eq $variable) {
    $entry = "";
    }
    }

    This method simply remodifies the $entry with a null value killing its data
    and the following \n inside the loop (at least I think it does).

    Both of these methods do the trick but I have a feeling that neither may be
    the most efficient way or worse these methods may have side effects that I
    am unaware of. Alot has changed in the world of Perl since I started using
    these methods and I wanted to know if there is a better/safer/more efficient
    way to do this.

    I would also like to ask about terminating a loop ... obviously after a
    match is found I would want to terminate the loop so that it doesn't waste
    time checking all the other array elements for a match. Suprisingly I was
    not able to source this answer. I once read somewhere that a command called
    "return" or something is used, thoughts?

    I appriciate you time on this, Thanks much,

    Robert
    Robert Valcourt, Dec 11, 2006
    #1
    1. Advertising

  2. Robert Valcourt wrote:
    >
    > For some time I have been using two different method for removing an entry
    > from an @rray. It is my beleif that these methods may be outdated or
    > erroneous and I wanted to get some opinions. My program reads the contents
    > of a text file, and places each line into the array. Here are my two
    > methods:
    >
    > Using Splicing
    > =========================
    >
    > open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    > @entries=<ADDRESSES>;
    > close(ADDRESSES);
    >
    > $variable = "Smith";
    >
    > foreach $entry(@entries) {
    > $location++;
    > if ($entry eq $variable) {
    > $location--;
    > $line = $location;
    > }
    > }
    >
    > splice(@entries, $line, 1);


    It looks like you want something like:

    open my $ADDRESSES, '<', 'addressbook.txt'
    or die "Can't open 'addressbook.txt' $!";

    my @entries = grep $entry ne $variable, <$ADDRESSES>;

    close $ADDRESSES;




    John
    --
    Perl isn't a toolbox, but a small machine shop where you can special-order
    certain sorts of tools at low cost and in short order. -- Larry Wall
    John W. Krahn, Dec 11, 2006
    #2
    1. Advertising

  3. Robert Valcourt

    -berlin.de Guest

    Robert Valcourt <> wrote in comp.lang.perl.misc:
    > Hello,
    >
    > For some time I have been using two different method for removing an entry
    > from an @rray. It is my beleif that these methods may be outdated or
    > erroneous and I wanted to get some opinions. My program reads the contents
    > of a text file, and places each line into the array. Here are my two
    > methods:
    >
    > Using Splicing
    > =========================
    >
    > open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    > @entries=<ADDRESSES>;
    > close(ADDRESSES);
    >
    > $variable = "Smith";
    >
    > foreach $entry(@entries) {
    > $location++;
    > if ($entry eq $variable) {
    > $location--;
    > $line = $location;
    > }
    > }
    >
    > splice(@entries, $line, 1);
    >
    > First of all I understand that many of you will first comment on the means
    > by which I read the text file and place its content into the array or that
    > strict isnt used above, and I will be fixing that soon using SLURP and
    > calling the "use strict" header.
    >
    > So this method uses the old splice routine. I find this method to be
    > confusing and im not quite a fan of it. On to the next:
    >
    > Redefining the @array element inside to loop
    > =========================
    >
    > open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    > @entries=<ADDRESSES>;
    > close(ADDRESSES);
    >
    > $variable = "Smith";
    >
    > foreach $entry(@entries) {
    > if ($entry eq $variable) {
    > $entry = "";
    > }
    > }
    >
    > This method simply remodifies the $entry with a null value killing its data
    > and the following \n inside the loop (at least I think it does).


    The methods don't do the same thing. The first one actually removes
    the entry from the array (the array length shrinks by one). The second
    method doesn't change the array but replaces the element with an empty
    string. After printing all entries both results look the same but the
    arrays are different after each one.

    > Both of these methods do the trick but I have a feeling that neither may be
    > the most efficient way or worse these methods may have side effects that I
    > am unaware of. Alot has changed in the world of Perl since I started using
    > these methods and I wanted to know if there is a better/safer/more efficient
    > way to do this.


    The simplest method (then and now) to remove an entry is grep:

    @entries = grep $_ ne $entry, @entries;

    > I would also like to ask about terminating a loop ... obviously after a
    > match is found I would want to terminate the loop so that it doesn't waste
    > time checking all the other array elements for a match. Suprisingly I was
    > not able to source this answer. I once read somewhere that a command called
    > "return" or something is used, thoughts?


    perldoc -f last.

    You can also use List::Util::first to find the entry efficiently
    (first() leaves the loop after the first match):

    my $i = List::Util::first { $_ eq $entry } @entries;
    splice @entries, $i, 1 if defined $i;

    This should be faster if the lists are very long. Just how long
    "very long" is can only be decided by benchmarks.

    Anno
    -berlin.de, Dec 11, 2006
    #3
  4. Robert Valcourt

    Mirco Wahab Guest

    Robert Valcourt wrote:
    > My program reads the contents
    > of a text file, and places each line into the array.
    > Here are my two methods:
    >
    > Using Splicing
    > =========================
    > ...
    > Redefining the @array element inside to loop
    > =========================
    >
    >


    Aside from Anno's and John's comments,
    I'd like to make another remark.

    Both of your variants won't work,
    becvause you can't simply 'eq' a
    variable against a string read from
    a file (which may at least contain a
    '\n' and probably a lot more)

    Suppose we have a simple "address file":

    Smarf Boomtown Boomstreet 23
    Smith Huntington Hunstreet 12
    Solch Berlin Berlstrasse 123

    Then you could read all except "Smith ..."
    (as the other posts suggested => grep) by
    "grep negated regex":

    ...
    my $variable = 'Smith';
    open (my $addresses, '<', 'addressbook.txt') or die "without remorse: $!";
    my @entries = grep !/\b$variable\b/, <$addresses>;
    ...

    (\bWORD\b) means: WORD must be delimited by word boundaries,
    so "Smithnwesson" woudn't match.

    > I would also like to ask about terminating a loop ... obviously after a
    > match is found I would want to terminate the loop so that it doesn't waste
    > time checking all the other array elements for a match. Suprisingly I was
    > not able to source this answer. I once read somewhere that a command called
    > "return" or something is used, thoughts?


    That's called 'last':

    ...
    ...
    for my $index (0..@entries-1) {
    if( $entries[$index] =~ /\b$variable\b/ ) {
    splice @entries, $index, 1;
    last;
    }
    }
    ...


    Regards

    M.
    Mirco Wahab, Dec 11, 2006
    #4
  5. Robert Valcourt

    Guest

    "Robert Valcourt" <> wrote:
    > Hello,
    >
    > For some time I have been using two different method for removing an
    > entry from an @rray. It is my beleif that these methods may be outdated
    > or erroneous and I wanted to get some opinions. My program reads the
    > contents of a text file, and places each line into the array. Here are my
    > two methods:
    >
    > Using Splicing
    > =========================
    >
    > open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    > @entries=<ADDRESSES>;
    > close(ADDRESSES);
    >
    > $variable = "Smith";
    >
    > foreach $entry(@entries) {
    > $location++;
    > if ($entry eq $variable) {
    > $location--;
    > $line = $location;
    > }
    > }
    >
    > splice(@entries, $line, 1);
    >
    > First of all I understand that many of you will first comment on the
    > means by which I read the text file and place its content into the array
    > or that strict isnt used above, and I will be fixing that soon using
    > SLURP and calling the "use strict" header.
    >
    > So this method uses the old splice routine.


    Old? I prefer the term "mature". Anyway, is there any reason you
    don't use a hash rather than an array? What happens if $variable doesn't
    occur at all in the list?


    > I find this method to be
    > confusing and im not quite a fan of it. On to the next:
    >
    > Redefining the @array element inside to loop
    > =========================
    >
    > open (ADDRESSES, "<addressbook.txt") or die "Can't open file: $!";
    > @entries=<ADDRESSES>;
    > close(ADDRESSES);
    >
    > $variable = "Smith";
    >
    > foreach $entry(@entries) {
    > if ($entry eq $variable) {
    > $entry = "";
    > }
    > }
    >
    > This method simply remodifies the $entry with a null value killing its
    > data and the following \n inside the loop (at least I think it does).


    This "removes" all matching entries, the first method removes only the last
    one. But it sounds like you anticipate there will be exactly one match?

    > Both of these methods do the trick but I have a feeling that neither may
    > be the most efficient way


    Is that really a concern?

    > or worse these methods may have side effects
    > that I am unaware of. Alot has changed in the world of Perl since I
    > started using these methods and I wanted to know if there is a
    > better/safer/more efficient way to do this.


    grep

    >
    > I would also like to ask about terminating a loop ... obviously after a
    > match is found I would want to terminate the loop so that it doesn't
    > waste time checking all the other array elements for a match.


    last

    > Suprisingly
    > I was not able to source this answer. I once read somewhere that a
    > command called "return" or something is used, thoughts?


    return can be used to break out of loops (as long as the loop is contained
    in a subroutine call or other "return"able construct) but one should only
    do that if your goal is both leave the loop and return from the outer
    construct. If you just want to leave the loop, use last.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Dec 11, 2006
    #5
    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. Vishal
    Replies:
    0
    Views:
    523
    Vishal
    Nov 14, 2003
  2. AtomicBob
    Replies:
    14
    Views:
    859
    Toby Inkster
    May 2, 2006
  3. Chris  Chiasson
    Replies:
    6
    Views:
    605
    Richard Tobin
    Nov 14, 2006
  4. Mike Owen

    Allowing entry of a Carriage Return during data entry

    Mike Owen, Jul 27, 2006, in forum: ASP .Net Web Controls
    Replies:
    3
    Views:
    681
    Alessandro Zifiglio
    Jul 27, 2006
  5. Noozer
    Replies:
    2
    Views:
    242
    Dr John Stockton
    Aug 1, 2005
Loading...

Share This Page