in reply to Incrementing string arrays when used with foreach loops

First off, thanks for the responses, it helped me figure this out, eventually.

I thought I'd update this thread with my final result in order to solicit comments. For my purposes, the script works but since I'm a beginner and don't have an instructor it would be good to get feedback on logic, style, most anything, really.

One area in particular I'm curious about is the inner foreach loop where I have the list of if tests. It seems like there should be a better way to populate the arrays instead of doing an if statement for each array because I know during each iteration which card is coming. One way I thought about doing this was to increment the array name for each iteration but couldn't figure out how to do it. I also thought about switch statements or using a long if/elseif/else structure.

foreach $suit (@allsuits) { my $i = 1; foreach my $card (@suitcards) { push( @arraysuit, "$card$suit" ); if ( $i == 1 ) { push( @aces, "$card$suit " ) } if ( $i == 2 ) { push( @twos, "$card$suit " ) } if ( $i == 3 ) { push( @threes, "$card$suit " ) } if ( $i == 4 ) { push( @fours, "$card$suit " ) } if ( $i == 5 ) { push( @fives, "$card$suit " ) } if ( $i == 6 ) { push( @sixes, "$card$suit " ) } if ( $i == 7 ) { push( @sevens, "$card$suit " ) } if ( $i == 8 ) { push( @eights, "$card$suit " ) } if ( $i == 9 ) { push( @nines, "$card$suit " ) } if ( $i == 10 ) { push( @tens, "$card$suit " ) } if ( $i == 11 ) { push( @jacks, "$card$suit " ) } if ( $i == 12 ) { push( @queens, "$card$suit " ) } if ( $i == 13 ) { push( @kings, "$card$suit " ) }
Here's the whole thing, with output. I apologize if this is long, I can't tell if the <readmore> tags are working.
#!/usr/bin/perl use strict; use warnings; my $suit; my @allsuits = ( "_clb", "_dmd", "_hrt", "_spd" ); my @suitcards = ( "a", 2 .. 10, "j", "q", "k" ); my @arraysuit; my ( @aces, @twos, @threes, @fours, @fives, @sixes, @sevens, @eights, @nines, @tens, @jacks, @queens, @kings ); my $randcard; my @hand; foreach $suit (@allsuits) { my $i = 1; foreach my $card (@suitcards) { push( @arraysuit, "$card$suit" ); if ( $i == 1 ) { push( @aces, "$card$suit " ) } if ( $i == 2 ) { push( @twos, "$card$suit " ) } if ( $i == 3 ) { push( @threes, "$card$suit " ) } if ( $i == 4 ) { push( @fours, "$card$suit " ) } if ( $i == 5 ) { push( @fives, "$card$suit " ) } if ( $i == 6 ) { push( @sixes, "$card$suit " ) } if ( $i == 7 ) { push( @sevens, "$card$suit " ) } if ( $i == 8 ) { push( @eights, "$card$suit " ) } if ( $i == 9 ) { push( @nines, "$card$suit " ) } if ( $i == 10 ) { push( @tens, "$card$suit " ) } if ( $i == 11 ) { push( @jacks, "$card$suit " ) } if ( $i == 12 ) { push( @queens, "$card$suit " ) } if ( $i == 13 ) { push( @kings, "$card$suit " ) } $i++; } } print "This is how many cards are in the deck: ", my $howmany = @array +suit, "\n"; print "These are the aces in the deck: ", @aces, "\n"; print "These are the twos in the deck: ", @twos, "\n"; print "These are the threes in the deck: ", @threes, "\n"; print "These are the fours in the deck: ", @fours, "\n"; print "These are the fives in the deck: ", @fives, "\n"; print "These are the sixes in the deck: ", @sixes, "\n"; print "These are the sevens in the deck: ", @sevens, "\n"; print "These are the eights in the deck: ", @eights, "\n"; print "These are the nines in the deck: ", @nines, "\n"; print "These are the tens in the deck: ", @tens, "\n"; print "These are the jacks in the deck: ", @jacks, "\n"; print "These are the queens in the deck: ", @queens, "\n"; print "These are the kings in the deck: ", @kings, "\n"; print "\n"; sub deal_cards(\@) { for ( my $n = 0 ; $n < 10 ; $n++ ) { push( @hand, $arraysuit[ rand @arraysuit ] ); } } sub remove_duplicates(\@) { my $ar = shift; my %seen; for ( my $i = 0 ; $i <= $#{$ar} ; ) { splice @$ar, --$i, 1 if $seen{ $ar->[ $i++ ] }++; } } deal_cards(@hand); print "10 random cards. Before checking for dupes:\n"; print "@hand\n\n"; remove_duplicates(@hand); print "Cards with duplicates removed:\n"; print "@hand\n\n"; while ( @hand < 10 ) { push( @hand, $arraysuit[ rand @arraysuit ] ); remove_duplicates(@hand); } print "Final hand:\n"; print "@hand\n"; This is how many cards are in the deck: 52 These are the aces in the deck: a_clb a_dmd a_hrt a_spd These are the twos in the deck: 2_clb 2_dmd 2_hrt 2_spd These are the threes in the deck: 3_clb 3_dmd 3_hrt 3_spd These are the fours in the deck: 4_clb 4_dmd 4_hrt 4_spd These are the fives in the deck: 5_clb 5_dmd 5_hrt 5_spd These are the sixes in the deck: 6_clb 6_dmd 6_hrt 6_spd These are the sevens in the deck: 7_clb 7_dmd 7_hrt 7_spd These are the eights in the deck: 8_clb 8_dmd 8_hrt 8_spd These are the nines in the deck: 9_clb 9_dmd 9_hrt 9_spd These are the tens in the deck: 10_clb 10_dmd 10_hrt 10_spd These are the jacks in the deck: j_clb j_dmd j_hrt j_spd These are the queens in the deck: q_clb q_dmd q_hrt q_spd These are the kings in the deck: k_clb k_dmd k_hrt k_spd 10 random cards. Before checking for dupes: 3_spd j_spd k_hrt 5_dmd a_spd j_clb 7_hrt k_hrt 2_hrt a_spd Cards with duplicates removed: 3_spd j_spd k_hrt 5_dmd a_spd j_clb 7_hrt 2_hrt Final hand: 3_spd j_spd k_hrt 5_dmd a_spd j_clb 7_hrt 2_hrt 9_clb 6_clb

Replies are listed 'Best First'.
Re^2: Incrementing string arrays when used with foreach loops
by toolic (Bishop) on Sep 11, 2008 at 01:10 UTC
    I can't tell if the <readmore> tags are working
    Yes, the <readmore> tags are working.
    it would be good to get feedback on logic, style, most anything, really

    As others have strongly hinted, only a single array is necessary. What you have is overly complicated. Rather than answer your pointed questions, consider the following code, which is really tilly's approach:

    use strict; use warnings; my @cards; for my $suit (qw(_clb _dmd _hrt _spd)) { for my $rank (2 .. 10, qw(j q k a)) { push @cards, $rank . $suit; } } for (1 .. 10) { my $index = int rand scalar @cards; print splice(@cards, $index, 1), "\n"; }

    Although the instructions do not explicitly call for using splice, it really is the right tool for the job of preventing random duplicates. Each time through the final for loop, a random element is removed from the @cards array.

      That kinda backwards thinking for a deck of cards. The normal thought process involves shuffling the deck then drawing from the top.

      use strict; use warnings; use List::Util qw( shuffle ); my @cards; for my $suit (qw(_clb _dmd _hrt _spd)) { for my $rank (2 .. 10, qw(j q k a)) { push @cards, $rank . $suit; } } my @deck = shuffle @cards; for (1 .. 10) { print(shift(@deck), "\n"); }
        I completely agree that using shuffle is a superior solution, but I was trying to illustrate a use of rand, according to the OP's recipe:
        c. The rand() function will be used to get a random card from the pack

        Wouldn't shift actually be considered dealing from the bottom of the deck? ;-}

Re^2: Incrementing string arrays when used with foreach loops
by gctaylor1 (Hermit) on Sep 11, 2008 at 14:08 UTC
    Wow. I see now I really was making this more complicated than it needed to be.

    I didn't even consider how much easier it would have been to remove the card from the deck and avoid the whole issue of looking for duplicates. Plus it's a more accurate representation of a real world scenario. I guess I needed to step back and evaluate the exercise instead of diving head first in to it. A valuable lesson.