Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Deleting Duplicates in an array

by blacksmith (Hermit)
on Jun 08, 2001 at 18:34 UTC ( [id://86912]=perlquestion: print w/replies, xml ) Need Help??

blacksmith has asked for the wisdom of the Perl Monks concerning the following question:

I am very new to the Amazing and Stunning world of PERL, so keep that in mind when I ask this question. I am trying to access a text file that I have created (owo.txt) and place the info into an array. I then need to extract and delete the duplicate entries. The order in which the program sorts the info is of little concern. What I have tried so far is below. This is placed after a loop in which the file is created. I get an error stating, "Modification of a read-only error at ... the line number is referring to 'undef @hsh{@ary};'". Could anyone help me on the mistake I am making. I appreciate it. Robert T Horn, CCNA $owo = "c:/scripts/owo.txt"; open (OWO, "+>$owo") or die $!; @ary = <OWO>; %hsh; undef @hsh{@ary}; @list = keys %hsh; print  @list;

Replies are listed 'Best First'.
Re: Deleting Duplicates in an array
by Abigail (Deacon) on Jun 08, 2001 at 20:16 UTC
    I'm trying to find out what you actually want to do with in your code.
    open (OWO, "+>$owo") or die $!;
    That opens your file for read/write, and then truncates it to be empty.
    @ary = <OWO>;
    The file is empty, so this makes @ary empty.
    %hsh;
    This should give you a warning, using a hash in void context. You do help yourself and use -w don't you?
    undef @hsh {@ary};
    Not quite sure what this is supposed to do. @ary is empty. So, you are undefining nothing at all. But, even if there was something to undefine, all it undefines is values, while the rest of the code uses keys. Hence, it seems to be pointless in stereo.
    @list = keys %hsh;
    I've a hard time figuring out the use of this statement. It only makes sense if %hsh was populated from code you didn't show.

    I would write the code somewhat like this (untested, may contain errors):

    open my $fh => "+< $owo" or die "Failed to open $owe: $!\n"; my %seen; my @unique = grep {!$seen {$_} ++} <$fh>; seek $fh, 0, 0 or die "Failed to seek $owe: $!\n"; print $fh @uniqe; truncate $fh => tell $fh or die "Failed to truncate $owe: $!\n"; close $fh;
    But it's shorter to write:
    system "sort -u $owe > $owe.tmp; mv $owe.tmp $owe";
    But that of course requires Unix, or Windows with a decent developers kit installed.

    -- Abigail

      Not quite sure what this is supposed to do. @ary is empty. So, you are undefining nothing at all. But, even if there was something to undefine, all it undefines is values, while the rest of the code uses keys. Hence, it seems to be pointless in stereo.
      No it' not pointless in stereo. undef undefes values, correct. But undef *defines* the *keys* of the values.
             all
        it undefines is values
      
      For a moment you had it there, to bad you didn't read your post.
(jeffa) Re: Deleting Duplicates in an array
by jeffa (Bishop) on Jun 08, 2001 at 18:50 UTC
    First USE STRICT!!!

    Having said that, let's try again:

    use strict; use IO::File; my $owo = IO::File->new('owo.txt') or die "no open $!"; my %hash = (); my @list = (); # updated, i was on crack or something - i actually said # to localize $/ to slurp the contents into an array . . . DOH! my @ary = <$owo>; foreach my $item (@ary) { push(@list,$item) unless $hash{$item}++; } print join("\n", @list), "\n";
    and that's it!

    Second pointer, i like IO::File, you don't have to use it, but if you like OO style, i highly recommend it.

    Third, go buy The Cookbook . . . that's where i learned to do this. :)

    Jeff

    R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
    L-L--L-L--L-L--L-L--L-L--L-L--L-L--
    
Re: Deleting Duplicates in an array
by rob_au (Abbot) on Jun 08, 2001 at 18:51 UTC
    Try this ...
     
    use strict; my ($owo) = "c:/script/owo.txt"; open (OWO, $owo) || die $!; my (@array, %hash); foreach (<OWO>) { # push the read line of the file into @array only if it has # not already been encountered # push (@array, $_) unless (defined($hash{$_})); # store the line as a key of a hash showing that it has been # read previously # $hash{$_} = 1; }; close (OWO); # Print the unduplicated collection of lines out to the file # open (OWO, ">$owo") || die $!; print OWO join("", @array); close (OWO); exit 0;

    Ooohhh, Rob no beer function well without!

Re: Deleting Duplicates in an array
by runrig (Abbot) on Jun 08, 2001 at 19:01 UTC
    perldoc is your friend:

    perldoc -q duplicate

Re: Deleting Duplicates in an array
by suaveant (Parson) on Jun 08, 2001 at 19:08 UTC
    The fact is, your code works fine, unless owo.txt is empty, and opening it like
    open (OWO, "+>$owo") or die $!; #in read-write mode seems to clear it #this line made it work fine for me... (in linux anyway) open (OWO, $owo) or die $!;
    you might also want to do
    chomp(@ary = <OWO>);
    to get rid of trailing newlines... up to you...

    if you do care about order from the file, you the suggestions others have posted.

                    - Ant

Re: Deleting Duplicates in an array
by Davious (Sexton) on Jun 08, 2001 at 21:10 UTC
    How about this?
    $owo = "c:/scripts/owo.txt"; open(FILE,"<$owo") || die $!; # read file my @list = keys %{{map{$_,1} <FILE>}}; # remove duplicates close(FILE); open(FILE,">$owo") || die $!; # write file foreach (@list) { chomp; print FILE "$_\n"; } close(FILE);

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://86912]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2024-04-16 08:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found