Your skill will accomplishwhat the force of many cannot PerlMonks

### Problems with looping through an array

by tcox (Novice)
 on May 27, 2004 at 10:16 UTC Need Help??

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

I am trying to fix an error I get when working on an array. The code below has an array with (8) 1s, (6) 2s, (2) 3s, (5) 4s, and (4) 5s. I need to figure this out in order for me to proceed to the next part of my program. If you notice the output below the code I am printing (9) 1s when it should only be 8. Does anyone in the Monastery have any thoughts?
```@ID = (1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,4,4,4,4,4,5,5,5,5);

\$evr_id = 0;
\$count = 1;
\$flag = 0;
\$processed = 1;

print "\n";

foreach \$a (@ID)
{
if(\$flag == 0)
{
\$evr_id = \$a;
print "\$processed) \$evr_id-\$count\n";
\$flag = 1;
\$count++;

}elsif(\$evr_id != \$a)
{
print "\$processed) \$evr_id-\$count\n\n";
\$count = 1;
\$evr_id = \$a;
\$flag = 0;

}else{
print "\$processed) \$a-\$count\n";
\$count++;
}
if(scalar(@ID) == \$processed)
{
print \$processed + 1 . ") \$a-\$count\n";

}
\$processed++;
}

OUTPUT:

1) 1-1
2) 1-2
3) 1-3
4) 1-4
5) 1-5
6) 1-6
7) 1-7
8) 1-8
9) 1-9

10) 2-1
11) 2-2
12) 2-3
13) 2-4
14) 2-5
15) 2-6

16) 3-1
17) 3-2

18) 4-1
19) 4-2
20) 4-3
21) 4-4
22) 4-5

23) 5-1
24) 5-2
25) 5-3
26) 5-4

Replies are listed 'Best First'.
Re: Problems with looping through an array
by gmax (Abbot) on May 27, 2004 at 10:34 UTC

Use a hash to get a count of each unique item.

```#!/usr/bin/perl -w
use strict;
use Data::Dumper;

my @ID = (1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,4,4,4,4,4,5,5,5,5);

#
# count
#
my %items =();
\$items{\$_}++ for @ID;

print "\$_ => \$items{\$_}\n" for sort keys %items;

#
# detail
#
%items =();
my \$count =0;
push @{\$items{\$_}}, \$count++ for @ID;

print Data::Dumper->Dump([ \%items], ['items']);

__END__
output:
1 => 8
2 => 6
3 => 2
4 => 5
5 => 4

\$items = {
'4' => [
16,
17,
18,
19,
20
],
'1' => [
0,
1,
2,
3,
4,
5,
6,
7
],
'3' => [
14,
15
],
'2' => [
8,
9,
10,
11,
12,
13
],
'5' => [
21,
22,
23,
24
]
};

(update) Instead of Data::Dumper, you could also get your details this way:

```print "\$_ => (@{\$items{\$_}})\n" for sort keys %items ;
__END__
1 => (0 1 2 3 4 5 6 7)
2 => (8 9 10 11 12 13)
3 => (14 15)
4 => (16 17 18 19 20)
5 => (21 22 23 24)

See also Perl Idioms Explained - keys %{{map{\$_=>1}@list}} in Tutorials to see how the hash mechanism works.

As for the error in your code, this node could be of help.

``` _  _ _  _
(_|| | |(_|><
_|
```
Re: Problems with looping through an array
by davis (Vicar) on May 27, 2004 at 10:33 UTC

I'm not too sure what your code is supposed to be doing. It looks a bit like you're trying to count the number of times a particular value occurs in an array. The normal way of doing this is to use a hash:

```#!/usr/bin/perl

use warnings;
use strict;

my @ID = qw/1 1 1 1 1 1 1 2 2 2 2 2 3 3 4 4 4 4 5 5 5 5 6/;

my %counts;
foreach my \$id (@ID) {
\$counts{\$id}++;
}

while(my (\$num, \$count) = each(%counts)) {
print "\$num : \$count\n";
}

But you might be trying to do something more complicated than that. Some more explanation of what you're trying to achieve would help

davis
It's not easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
Re: Problems with looping through an array
by antirice (Priest) on May 27, 2004 at 10:45 UTC

Wow, that's some funky code there. Rearrange it a little and you get what you wanted:

```@ID = (1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,4,4,4,4,4,5,5,5,5);

\$evr_id = undef;
\$count = 0;
\$flag = 0;
\$processed = 1;

print "\n";

foreach \$a (@ID)
{
if (\$evr_id != \$a) {
\$count = 1;
\$evr_id = \$a;
print "\n\$processed) \$a-\$count\n";
} else {
\$count++;
print "\$processed) \$a-\$count\n";
}
\$processed++;
}

If you just want counts, then you probably want the other two solutions. If you're looking for series, then this would probably be preferred.

antirice
The first rule of Perl club is - use Perl
The
ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Problems with looping through an array
by hv (Prior) on May 27, 2004 at 11:48 UTC

When you encounter a new value:

```    elsif(\$evr_id != \$a) {
print "\$processed) \$evr_id-\$count\n\n";
\$count = 1;
...
it s correct to initialise the count to 1, because you've just seen the first example of the new value.

When you first enter the loop, though, you haven't yet seen the first example of the initial number. So you should be initialising \$count to 0 before the loop, not 1.

Hugo

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://356853]
Approved by gmax
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-05-22 04:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?

No recent polls found