For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > May 2004 > Array with unique elements only









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Array with unique elements only
Mark Martin

2004-05-20, 8:30 am

Hi,
I'm moving database data from table to table and want to make sure I'm
getting only unique records.

Only want unique $field1 and was looking at the cookbook code, but for that
I have to populate a hash and then re-inspect through before inserting
uniques, something like :

%ucnt = ();
while (my @row = $sth->fetchrow) {

$field1 = $row[0];
push(@list,$field1 );
$ucnt{$_}++;
$field2 = $row[3];
}

@uniq = sort keys %ucnt;
foreach $item (@uniq) {
POPULATE TABLE............
}


Surely I can avoid the "foreach" and inspect $field1 in the while loop for
uniqueness before pushing it to an array.

Cheers,
Mark

Ramprasad A Padmanabhan

2004-05-20, 9:30 am

Wow,
unique items is surely an FAQ.
But here you dont need to filter the array, just see the answer inline

On Thu, 2004-05-20 at 17:07, Mark Martin wrote:
> Hi,
> I'm moving database data from table to table and want to make sure I'm
> getting only unique records.
>
> Only want unique $field1 and was looking at the cookbook code, but for that
> I have to populate a hash and then re-inspect through before inserting
> uniques, something like :
>
> %ucnt = ();
> while (my @row = $sth->fetchrow) {
>
> $field1 = $row[0];
> push(@list,$field1 );
> $ucnt{$_}++;
> $field2 = $row[3];
> }
>


Change that to
%ucnt = ();
while (my @row = $sth->fetchrow) {
$field1 = $row[0];
push(@list,$field1 );
$field2 = $row[3];

next if($ucnt{$_}++);
POPULATE TABLE .......................
}


> Surely I can avoid the "foreach" and inspect $field1 in the while loop for
> uniqueness before pushing it to an array.
>
> Cheers,
> Mark
>


Jeff 'Japhy' Pinyan

2004-05-20, 9:30 am

On May 20, Mark Martin said:

>I'm moving database data from table to table and want to make sure I'm
>getting only unique records.


This is similar to a topic that came up two days ago.

>Only want unique $field1 and was looking at the cookbook code, but for that
>I have to populate a hash and then re-inspect through before inserting
>uniques, something like :
>
>%ucnt = ();
>while (my @row = $sth->fetchrow) {
> $field1 = $row[0];
> push(@list,$field1 );
> $ucnt{$_}++;
> $field2 = $row[3];
>}
>
>@uniq = sort keys %ucnt;
>foreach $item (@uniq) {
>POPULATE TABLE............
>}
>
>
>Surely I can avoid the "foreach" and inspect $field1 in the while loop for
>uniqueness before pushing it to an array.


You *can't* know something is unique until you've looked through all your
data, but you CAN tell when something is NOT unique. You could do:

my (%count, %unique);

while (my @row = $sth->fetchrow) {
my $field = $row[0];
if ($count{$field}++) { delete $unique{$field} }
else { $unique{$field} = [ @row ] }; # or 1, or whatever you want
}

Here, every time a row is seen, its count is incremented. If the count
(before incrementing) was true (that is, not 0), then we delete it from
the unique hash. If the count was false (that is, 0), then we add it to
the unique hash.

This way you don't have to traverse over the %count hash for those
elements whose value is 1, you have a hash of the elements in %count whose
count is 1 already, the %unique hash.

Does this solve your problem?

--
Jeff "japhy" Pinyan japhy@pobox.com http://www.pobox.com/~japhy/
RPI Acacia brother #734 http://www.perlmonks.org/ http://www.cpan.org/
CPAN ID: PINYAN [Need a programmer? If you like my work, let me know.]
<stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.

Jeff 'Japhy' Pinyan

2004-05-20, 9:30 am

On May 20, Jeff 'japhy' Pinyan said:

> my (%count, %unique);
>
> while (my @row = $sth->fetchrow) {
> my $field = $row[0];
> if ($count{$field}++) { delete $unique{$field} }
> else { $unique{$field} = [ @row ] }; # or 1, or whatever you want
> }
>
>Here, every time a row is seen, its count is incremented. If the count
>(before incrementing) was true (that is, not 0), then we delete it from
>the unique hash. If the count was false (that is, 0), then we add it to
>the unique hash.
>
>This way you don't have to traverse over the %count hash for those
>elements whose value is 1, you have a hash of the elements in %count whose
>count is 1 already, the %unique hash.


I'm afraid I may have solved a different problem than the one you asked,
mainly because you didn't show us what you did WITH the hash you created.
I thought you wanted to work with elements that only appeared once, but
Rampra has code that makes it look like you want to make sure you don't
do something to the same row twice.

So his code is probably what you want.

But, wait. Why not add a DISTINCT clause to your SQL?

--
Jeff "japhy" Pinyan japhy@pobox.com http://www.pobox.com/~japhy/
RPI Acacia brother #734 http://www.perlmonks.org/ http://www.cpan.org/
CPAN ID: PINYAN [Need a programmer? If you like my work, let me know.]
<stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.

Rob Dixon

2004-05-20, 12:31 pm

Rampra A Padmanabhan wrote:
>
> Wow,
> unique items is surely an FAQ.
> But here you dont need to filter the array, just see the answer inline
>
> On Thu, 2004-05-20 at 17:07, Mark Martin wrote:
>
> Change that to
> %ucnt = ();
> while (my @row = $sth->fetchrow) {
> $field1 = $row[0];
> push(@list,$field1 );
> $field2 = $row[3];
>
> next if($ucnt{$_}++);
> POPULATE TABLE .......................
> }


....except that $_ isn't being assigned here. Something like this
should be closer.

HTH,

Rob


my $sth;

my @list;
my %count;

while (my @row = $sth->fetchrow) {

my $field1 = $row[0];
push(@list, $field1);

my $field2 = $row[3];

unless ($count{$field1}++) {
# POPULATE TABLE .......................
}
}




Mark Martin

2004-05-21, 5:30 am

Thanks Rampra - that works.

At 17:29 20/05/2004 +0530, Rampra A Padmanabhan wrote:[color=darkred]
>Wow,
>unique items is surely an FAQ.
>But here you dont need to filter the array, just see the answer inline
>
>On Thu, 2004-05-20 at 17:07, Mark Martin wrote:
> that
>
>Change that to
>%ucnt = ();
>while (my @row = $sth->fetchrow) {
> $field1 = $row[0];
> push(@list,$field1 );
> $field2 = $row[3];
>
> next if($ucnt{$_}++);
> POPULATE TABLE .......................
>}
>
>

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com