Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Limit loop

by htmanning (Friar)
on Aug 30, 2022 at 19:54 UTC ( #11146507=perlquestion: print w/replies, xml ) Need Help??

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

Monks, I have a database field called favorites with 3 pieces of information. Each favorite is separated by 3 tildes like this~~~. I loop through and pull out a number to set to a string like this:
@favs = split /~~~/,$favorites; $favnum = ""; foreach (@favs){ ($favtitle,$favlink,$favnum) = split /\|\|\|/,$_; $favnums=$favnum . "," . $favnums; } #end foreach (@favs){
A few of these favorite fields have more than 25 favs in them, and I want to limit the number that go into $favnums to 25. How do I stop the loop when I hit 25 and just ignore the rest?

Replies are listed 'Best First'.
Re: Limit loop
by pryrt (Abbot) on Aug 30, 2022 at 20:10 UTC

  • use the LIMIT term of split: @favs = split /~~~/,$favorites, 25;
  • use a counter inside the loop, and last when the counter is above 25: state $counter=0; last if ++$counter>=25;
      To nitpick my own: the split-with-LIMIT put all the remaining favorites with ~~~ between (#25-30 in my example) in slot#25, which isn't what I intended. I changed the limit to 26, then dropped the last element if there were more than 25.

      The code below shows that failure, plus the fixed version, plus the working counter-based solution.

Re: Limit loop
by johngg (Canon) on Aug 30, 2022 at 21:59 UTC

    Truncate the @favs array before entering the loop if it has more than 25 elements. Setting $#favs to 24 is setting the index of the last element so that the array now has 25 elements, 0 through 24.

    johngg@shiraz ~ % perl -Mstrict -Mwarnings -E ' my @favs = ( q{a} .. q{z} ); say qq{@favs}; $#favs = 24 if scalar @favs > 25; say qq{@favs};' a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y

    I hope this is helpful.



Re: Limit loop
by NERDVANA (Hermit) on Aug 31, 2022 at 17:17 UTC
    While others have helped you with your current problem of splitting the column, I'm going to suggest that your future problem will be that you didn't normalize your database and put the favorites in their own related table. It seems highly likely that some day you might want to write a SQL query to find out which favorites link to which sites, or rewrite some URLs in the favorites, and you could do it more easily if favorites were a table.
    -- supposing favorites are attached to user records CREATE TABLE user_favorites ( userid integer not null, title varchar(100) not null, link varchar(255) not null, num integer not null, PRIMARY KEY (userid, title), FOREIGN KEY (userid) REFERENCES users (userid) ON DELETE CASCADE );

    Or, even if you hate the idea of a second table, you could store favorites as JSON and on most modern databases you can also reach into that with SQL.

      Totally agree. I need to create a separate table for favorites. It's an absolute mess the way it is. Thank you!
Re: Limit loop
by tybalt89 (Monsignor) on Aug 30, 2022 at 22:13 UTC
    #!/usr/bin/perl use strict; # use warnings; for my $n ( 24, 25, 26 ) { my $favorites = join '~~~', map "a|||b|||$_", 1 .. $n; my $favnums = join '', reverse map ',' . (split /\|{3}/ )[2], grep defined, ( split /~~~/, $favorites, 26 )[0 .. 24]; print "n = $n\n\n$favorites\n\n$favnums\n\n"; }


    n = 24 a|||b|||1~~~a|||b|||2~~~a|||b|||3~~~a|||b|||4~~~a|||b|||5~~~a|||b|||6~ +~~a|||b|||7~~~a|||b|||8~~~a|||b|||9~~~a|||b|||10~~~a|||b|||11~~~a|||b +|||12~~~a|||b|||13~~~a|||b|||14~~~a|||b|||15~~~a|||b|||16~~~a|||b|||1 +7~~~a|||b|||18~~~a|||b|||19~~~a|||b|||20~~~a|||b|||21~~~a|||b|||22~~~ +a|||b|||23~~~a|||b|||24 ,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 n = 25 a|||b|||1~~~a|||b|||2~~~a|||b|||3~~~a|||b|||4~~~a|||b|||5~~~a|||b|||6~ +~~a|||b|||7~~~a|||b|||8~~~a|||b|||9~~~a|||b|||10~~~a|||b|||11~~~a|||b +|||12~~~a|||b|||13~~~a|||b|||14~~~a|||b|||15~~~a|||b|||16~~~a|||b|||1 +7~~~a|||b|||18~~~a|||b|||19~~~a|||b|||20~~~a|||b|||21~~~a|||b|||22~~~ +a|||b|||23~~~a|||b|||24~~~a|||b|||25 ,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 n = 26 a|||b|||1~~~a|||b|||2~~~a|||b|||3~~~a|||b|||4~~~a|||b|||5~~~a|||b|||6~ +~~a|||b|||7~~~a|||b|||8~~~a|||b|||9~~~a|||b|||10~~~a|||b|||11~~~a|||b +|||12~~~a|||b|||13~~~a|||b|||14~~~a|||b|||15~~~a|||b|||16~~~a|||b|||1 +7~~~a|||b|||18~~~a|||b|||19~~~a|||b|||20~~~a|||b|||21~~~a|||b|||22~~~ +a|||b|||23~~~a|||b|||24~~~a|||b|||25~~~a|||b|||26 ,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1
      Thanks. This is an example of the $favorites field:
      Adam Knowles||||||11977~~~Alex Burleson| +|||||27627~~~Billy||| +om/?ID=18836|||18836~~~Billy||||||18836 +~~~Christopher Duarte||||||14713~~~Dave + Martin||||||5590~~~Drew Rubado|||https: +//|||26867~~~Emily Hanson||| +m/?ID=6782|||6782~~~James Gehrke||||||78 +34~~~Jeff Banta||||||11446~~~Jeffrey P +Sandoval||||||14637~~~Jesse Bollinger|| +||||8034~~~Jonathan Walker|||https://www|||4811~~~Jordan Hall||| +549|||12549~~~Joseph Dodds||||||26211~~ +~Mark Tappan||||||5370~~~Mary Christine +Hammill-Perkins||||||15901~~~Mary E. Bo +esch||||||20326~~~Matthew Smith|||https +://|||26752~~~Matthew Tuggle||||||13170~~~Moises Cariaso||| +397|||27397~~~Nicole Masciola||||||2723 +0~~~Paul Zenns||||||8396~~~Paul Zenns||| +|||8396~~~Phillip Scott||||||5015~~~Ross Martin||| +|||27192~~~Sam Lavine||||||26277~~~Step +hen Beatty Jr||||||10557~~~TODD A PARTI +N||||||21876~~~
      Unfortunately I'm just a hack and I didn't write this. It looks like the last number gets stuffed into the $favnums var and that is stuffed into a cookie. I think it's too long for the cookie to handle if there are more than 25 favorites or so which is why I'm trying to chop it down. I'm sure I'm doing something wrong but none of these suggestions have led me to the answer. I've tried setting a counter to zero and adding one to the counter at the end of the loop and then telling it to stop if it reaches 25, but I must be doing something wrong because it doesn't work. I'll keep trying. Thank you for all who have attempted to help.
        now that you show the actual data, I would just get the nums from the end of the lines via match global, thusly:
        use strict; use warnings; my $str = 'Adam Knowles||||||11977~~~Ale +x Burleson||||||27627~~~Billy|||https:/ +/|||18836~~~Billy||| +836|||18836~~~Christopher Duarte||||||1 +4713~~~Dave Martin||||||5590~~~Drew Ruba +do||||||26867~~~Emily Hanson|||https://|||6782~~~James Gehrke||| +D=7834|||7834~~~Jeff Banta||||||11446~~ +~Jeffrey P Sandoval||||||14637~~~Jesse +Bollinger||||||8034~~~Jonathan Walker||| +|||4811~~~Jordan Hall||||||12549~~~Joseph Dodds||| +1|||26211~~~Mark Tappan||||||5370~~~Mary + Christine Hammill-Perkins||||||15901~~ +~Mary E. Boesch||||||20326~~~Matthew Sm +ith||||||26752~~~Matthew Tuggle|||https +://|||13170~~~Moises Cariaso||||||27397~~~Nicole Masciola||| +7230|||27230~~~Paul Zenns||||||8396~~~Pa +ul Zenns||||||8396~~~Phillip Scott|||htt +ps://|||5015~~~Ross Martin||| +m/?ID=27192|||27192~~~Sam Lavine||||||2 +6277~~~Stephen Beatty Jr||||||10557~~~T +ODD A PARTIN||||||21876~~~'; my @favnums = $str =~ /\|\|\|(\d+)~/g; $#favnums = 24 if ($#favnums >24); #maximum of 25 fav's my $favnumstr = join ",",@favnums; print $favnumstr; 11977,27627,18836,18836,14713,5590,26867,6782,7834,11446,14637,8034,48 +11,12549,26211,5370,15901,20326,26752,13170,27397,27230,8396,8396,501 +5
Re: Limit loop
by jwkrahn (Monsignor) on Aug 30, 2022 at 20:42 UTC
                  foreach ( @favs[ 0 .. 24 ] ) {

      Since the original post said only "a few of these favorite fields have more than 25", then most of the time, that will end up with one or more undef iterations on the loop, so then undef would have to be handled specially. Maybe via next unless defined; or similar logic.

        Thanks but this didn't work. It just throws the same end of script output before header error. And YES, most of them have less than 25 favs but some do have more. Most of the time this is a non issue.

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (1)
As of 2023-06-08 04:04 GMT
Find Nodes?
    Voting Booth?
    How often do you go to conferences?

    Results (29 votes). Check out past polls.