1 8f7f2f4a 2021-12-17 jrmu ================================================================================
5 8f7f2f4a 2021-12-17 jrmu each() lets you iterate through each key-value pair in a hash:
10 8f7f2f4a 2021-12-17 jrmu my %pets = (
20 8f7f2f4a 2021-12-17 jrmu while(my($pet,$qty)=each(%pets)) {
22 8f7f2f4a 2021-12-17 jrmu print "pet='$pet', qty='$qty'\n";
27 8f7f2f4a 2021-12-17 jrmu > pet='cats', qty='2'
29 8f7f2f4a 2021-12-17 jrmu > pet='dogs', qty='1'
31 8f7f2f4a 2021-12-17 jrmu > pet='fish', qty='3'
34 8f7f2f4a 2021-12-17 jrmu Every call to each() returns the next key/value pair in the hash. After
35 8f7f2f4a 2021-12-17 jrmu the last key/value pair is returned, the next call to each() will return
36 8f7f2f4a 2021-12-17 jrmu an empty list, which is boolean false. This is how the while loop is
37 8f7f2f4a 2021-12-17 jrmu able to loop through each key/value and then exit when done.
40 8f7f2f4a 2021-12-17 jrmu Every hash has one "each iterator" attached to it. This iterator is used
41 8f7f2f4a 2021-12-17 jrmu by perl to remember where it is in the hash for the next call to each().
43 8f7f2f4a 2021-12-17 jrmu Calling keys() on the hash will reset the iterator. The list returned by
44 8f7f2f4a 2021-12-17 jrmu keys() can be discarded.
47 8f7f2f4a 2021-12-17 jrmu keys(%hash);
50 8f7f2f4a 2021-12-17 jrmu Do not add keys while iterating a hash with each().
53 8f7f2f4a 2021-12-17 jrmu You can delete keys while iterating a hash with each().
56 8f7f2f4a 2021-12-17 jrmu The each() function does not have to be used inside a while loop. This
57 8f7f2f4a 2021-12-17 jrmu example uses a subroutine to call each() once and print out the result.
58 8f7f2f4a 2021-12-17 jrmu The subroutine is called multiple times without using a while() loop.
60 8f7f2f4a 2021-12-17 jrmu Calling keys() on the hash will reset the iterator. The list returned by
61 8f7f2f4a 2021-12-17 jrmu keys() can be discarded.
64 8f7f2f4a 2021-12-17 jrmu keys(%hash);
67 8f7f2f4a 2021-12-17 jrmu Do not add keys while iterating a hash with each().
70 8f7f2f4a 2021-12-17 jrmu You can delete keys while iterating a hash with each().
73 8f7f2f4a 2021-12-17 jrmu The each() function does not have to be used inside a while loop. This
74 8f7f2f4a 2021-12-17 jrmu example uses a subroutine to call each() once and print out the result.
75 8f7f2f4a 2021-12-17 jrmu The subroutine is called multiple times without using a while() loop.
77 8f7f2f4a 2021-12-17 jrmu my %pets = (
88 8f7f2f4a 2021-12-17 jrmu sub one_time {
90 8f7f2f4a 2021-12-17 jrmu my($pet,$qty)=each(%pets);
92 8f7f2f4a 2021-12-17 jrmu # if key is not defined,
94 8f7f2f4a 2021-12-17 jrmu # then each() must have hit end of hash
96 8f7f2f4a 2021-12-17 jrmu if(defined($pet)) {
98 8f7f2f4a 2021-12-17 jrmu print "pet='$pet', qty='$qty'\n";
102 8f7f2f4a 2021-12-17 jrmu print "end of hash\n";
109 8f7f2f4a 2021-12-17 jrmu one_time; # cats
111 8f7f2f4a 2021-12-17 jrmu one_time; # dogs
113 8f7f2f4a 2021-12-17 jrmu keys(%pets); # reset the hash iterator
115 8f7f2f4a 2021-12-17 jrmu one_time; # cats
117 8f7f2f4a 2021-12-17 jrmu one_time; # dogs
119 8f7f2f4a 2021-12-17 jrmu one_time; # fish
121 8f7f2f4a 2021-12-17 jrmu one_time; # end of hash
123 8f7f2f4a 2021-12-17 jrmu one_time; # cats
125 8f7f2f4a 2021-12-17 jrmu one_time; # dogs
128 8f7f2f4a 2021-12-17 jrmu > pet='cats', qty='2'
130 8f7f2f4a 2021-12-17 jrmu > pet='dogs', qty='1'
132 8f7f2f4a 2021-12-17 jrmu > pet='cats', qty='2'
134 8f7f2f4a 2021-12-17 jrmu > pet='dogs', qty='1'
136 8f7f2f4a 2021-12-17 jrmu > pet='fish', qty='3'
138 8f7f2f4a 2021-12-17 jrmu > end of hash
140 8f7f2f4a 2021-12-17 jrmu > pet='cats', qty='2'
142 8f7f2f4a 2021-12-17 jrmu > pet='dogs', qty='1'
145 8f7f2f4a 2021-12-17 jrmu There is only one iterator variable connected with each hash, which
146 8f7f2f4a 2021-12-17 jrmu means calling each() on a hash in a loop that then calls each() on the
147 8f7f2f4a 2021-12-17 jrmu same hash another loop will cause problems. The example below goes
148 8f7f2f4a 2021-12-17 jrmu through the %pets hash and attempts to compare the quantity of different
149 8f7f2f4a 2021-12-17 jrmu pets and print out their comparison.
152 8f7f2f4a 2021-12-17 jrmu my %pets = (
162 8f7f2f4a 2021-12-17 jrmu while(my($orig_pet,$orig_qty)=each(%pets)) {
164 8f7f2f4a 2021-12-17 jrmu while(my($cmp_pet,$cmp_qty)=each(%pets)) {
166 8f7f2f4a 2021-12-17 jrmu if($orig_qty>$cmp_qty) {
168 8f7f2f4a 2021-12-17 jrmu print "there are more $orig_pet "
170 8f7f2f4a 2021-12-17 jrmu ."than $cmp_pet\n";
174 8f7f2f4a 2021-12-17 jrmu print "there are less $orig_pet "
176 8f7f2f4a 2021-12-17 jrmu ."than $cmp_pet\n";
186 8f7f2f4a 2021-12-17 jrmu > there are more cats than dogs
188 8f7f2f4a 2021-12-17 jrmu > there are less cats than fish
190 8f7f2f4a 2021-12-17 jrmu > there are more cats than dogs
192 8f7f2f4a 2021-12-17 jrmu > there are less cats than fish
194 8f7f2f4a 2021-12-17 jrmu > there are more cats than dogs
196 8f7f2f4a 2021-12-17 jrmu > there are less cats than fish
198 8f7f2f4a 2021-12-17 jrmu > there are more cats than dogs
200 8f7f2f4a 2021-12-17 jrmu > there are less cats than fish
204 8f7f2f4a 2021-12-17 jrmu The outside loop calls each() and gets "cats". The inside loop calls
205 8f7f2f4a 2021-12-17 jrmu each() and gets "dogs". The inside loop continues, calls each() again,
206 8f7f2f4a 2021-12-17 jrmu and gets "fish". The inside loop calls each() one more time and gets an
207 8f7f2f4a 2021-12-17 jrmu empty list. The inside loop exits. The outside loop calls each() which
208 8f7f2f4a 2021-12-17 jrmu continues where the inside loop left off, namely at the end of the list,
209 8f7f2f4a 2021-12-17 jrmu and returns "cats". The code then enters the inside loop, and the
210 8f7f2f4a 2021-12-17 jrmu process repeats itself indefinitely.
213 8f7f2f4a 2021-12-17 jrmu One solution for this each() limitation is shown below. The inner loop
214 8f7f2f4a 2021-12-17 jrmu continues to call each() until it gets the key that matches the outer
215 8f7f2f4a 2021-12-17 jrmu loop key. The inner loop must skip the end of the hash (an undefined
216 8f7f2f4a 2021-12-17 jrmu key) and continue the inner loop. This also fixes a problem in the above
217 8f7f2f4a 2021-12-17 jrmu example in that we probably do not want to compare a key to itself.
220 8f7f2f4a 2021-12-17 jrmu my %pets = (
231 8f7f2f4a 2021-12-17 jrmu while(my($orig_pet,$orig_qty)=each(%pets)) {
235 8f7f2f4a 2021-12-17 jrmu my($cmp_pet,$cmp_qty)=each(%pets);
237 8f7f2f4a 2021-12-17 jrmu next unless(defined($cmp_pet));
239 8f7f2f4a 2021-12-17 jrmu last if($cmp_pet eq $orig_pet);
241 8f7f2f4a 2021-12-17 jrmu if($orig_qty>$cmp_qty) {
243 8f7f2f4a 2021-12-17 jrmu print "there are more $orig_pet "
245 8f7f2f4a 2021-12-17 jrmu ."than $cmp_pet\n";
249 8f7f2f4a 2021-12-17 jrmu print "there are less $orig_pet "
251 8f7f2f4a 2021-12-17 jrmu ."than $cmp_pet\n";
261 8f7f2f4a 2021-12-17 jrmu > there are more cats than dogs
263 8f7f2f4a 2021-12-17 jrmu > there are less cats than fish
265 8f7f2f4a 2021-12-17 jrmu > there are less dogs than fish
267 8f7f2f4a 2021-12-17 jrmu > there are less dogs than cats
269 8f7f2f4a 2021-12-17 jrmu > there are more fish than cats
271 8f7f2f4a 2021-12-17 jrmu > there are more fish than dogs
274 8f7f2f4a 2021-12-17 jrmu If you do not know the outer loop key, either because its in someone
275 8f7f2f4a 2021-12-17 jrmu else's code and they do not pass it to you, or some similar problem,
276 8f7f2f4a 2021-12-17 jrmu then the only other solution is to call keys on the hash for all inner
277 8f7f2f4a 2021-12-17 jrmu loops, store the keys in an array, and loop through the array of keys
278 8f7f2f4a 2021-12-17 jrmu using foreach. The inner loop will then not rely on the internal hash
279 8f7f2f4a 2021-12-17 jrmu iterator value.