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

Hey Monks,

I am trying to find out if there is another way to remove an element from an array. I am playing around with a script to deal a hand of poker and I found tachyon's post showing how to do this and it works well, but my script doesn't always know how many cards each player will take.

@cards has all the cards in a deck.

$hand11 = $cards[rand(@cards)]; @cards1 = grep{$_ ne $hand11}@cards; $hand12 = $cards1[rand(@cards1)]; @cards2 = grep{$_ ne $hand12}@cards1;
Thanks,
sk

Replies are listed 'Best First'.
Re: finding and deleting an element from array
by Zaxo (Archbishop) on Sep 05, 2003 at 14:43 UTC

    The usual way is to do Fisher-Yates shuffle on @cards and deal from the top with pop.

    If you wish to pull from a deck with rand, splice is nice.

    After Compline,
    Zaxo

      I'll fill in the blanks, for Zaxo's suggestion to use splice:
      push @hand, splice @cards, int rand @cards, 1;
      You can do this as many times as you wish, to get a full hand.
      Gotcha, guess I was doing it backwards.

      Thanks for the replies.
Re: finding and deleting an element from array
by Abigail-II (Bishop) on Sep 05, 2003 at 15:01 UTC
    That's kind of inefficient. For each card selected, you compare all remaining cards in the deck with the selected card. Now, considering a deck only has 52 cards, it doesn't really matter (unless you've the deal millions of hands), but the principle curls my toes.

    Do what humans normally do: before dealing the cards, shuffle them, then deal from the top. Cutting the deck isn't necessary. ;-)

    Abigail

      I suspect that if Abigail-II were shuffling & dealing, I'd demand someone else cut first - been burnt like that before...:)

      Ben

Re: finding and deleting an element from array
by benn (Vicar) on Sep 05, 2003 at 15:13 UTC
    More as a general point about this class of problem, it's my turn to repeat the well-worn advice about "whenever you start finding yourself with variables ending with incremental numbers, it's time to use arrays instead."

    There's nothing at all wrong with assigning an array to a grep'ed version of itself, any more than there is map'ing one - you really don't need @cards1, @cards2 etc.

    As Zaxo said, shuffling and popping would be better here, but should you wish to do this (or similar) "in place" as you are doing, something like this would be easier...

    while (@hand < $num_to_deal) { return "no more cards" unless @cards; push @hand,$cards[int(rand(@cards))]; @cards = grep{$_ ne $hand[$#hand]}@cards; }
    NB - I'm not advocating this code - as others have said, the grep is nasty - just pointing out a principle :)

    Cheers, Ben.