Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Deleting certein elements from an array

by haukex (Archbishop)
on Feb 07, 2019 at 09:42 UTC ( [id://1229526]=note: print w/replies, xml ) Need Help??


in reply to Deleting certein elements from an array

I think a good first step would be to clean up your logic a bit. You've got two while ($all_the_numbers<20) loops, but $all_the_numbers is initialized as a random number from 0 to 18 and never changed - so those are essentially infinite loops. You exit them via last and the loop counters $i and $h, so really, those two loops can be replaced by for loops. More specifically, in the following I've used the more Perlish foreach loop with a range operator, and since you only use the variables $i and $h to ensure the loop runs $all_the_numbers times, I've removed those variable names entirely. The new loops have an added benefit: in your original code, if $all_the_numbers was zero, your code would drop into an infinite loop - maybe you can see why? (Hint: Add a say $i; right before the comparison to $all_the_numbers.)

#!/usr/bin/env perl use warnings; use strict; use feature qw/say/; my $all_the_numbers=int(rand(19)); say "$all_the_numbers"; my @rand=(); for (1..$all_the_numbers) { push @rand, 20-int(rand(30)); } say "@rand"; for (1..$all_the_numbers) { for (@rand) { if ( $rand[0]<0 ) { next; } # skip the negative ones shift @rand; } } say "@rand";

Now, I hope that's easier to read. As for your logic: Note that shift removes the first item off the list, not the current one. If you wanted to do that, you'd need to do something like splice, however, that's tricky because it edits the array you're currently looping over, changing the indices. You said "this resoults in deleting only the positive numbers" - notice that your logic currently says: "Loop over the elements of @rand, each time checking if the first element of @rand is less than zero, and if it is, skip the rest of the loop (i.e. the shift)". Skipping the rest of the loop can also be expressed as follows*: "Loop over the elements of @rand, each time testing the first element of @rand, if that element is greater than or equal to zero, remove it from the array." I hope this explanation helps make it clear what is going wrong?

Now, as for how to fix it, I think I have to suggest re-thinking your overall logic. This is one of those cases where working out the issue on paper would be beneficial, especially if you are required to operate on the array in-place. For each iteration of the loop, keep track (on paper) of the loop counter, the contents of the array, which item you want to remove, and so on. If you are not required to operate on the array in-place, then Perl provides a handy function to make the task of keeping only certain items of an array very easy - have a look at grep.

* Update: Breaking that down:

for (@rand) { if ( $rand[0]<0 ) { next; } shift @rand; }

Can be written as:

for (@rand) { if ( $rand[0]<0 ) { next; } else { shift @rand; } }

Which can be written as:

for (@rand) { if ( $rand[0]>=0 ) { shift @rand; } else { next; } }

And the else { next; } can be removed.

Update 2: Added more links to text, and minor changes to wording.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-25 15:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found