Search code examples
pythonlist-comparison

check if a list contains 4 elements of the same value


So I'm stuck on a newbie problem once more :D

I'm trying to mash together a text based game of go-fish against the computer.

Ok so 1 card is actually a tuple of elements from two lists.

suits = ['Clubs', 'Diamonds', 'Spade', 'Hearts']
ranks = [None, 'ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king']

Then that is added to a deck and shuffled and whatnot and then dealt into hands. (got most of it from the book thinkpython i think. Learned a lot about class structure and inheritance in the process.)

So one hand might look like this

['Clubs 2', 'Diamonds king', 'Diamonds 2', 'Spades 2', 'Hearts 2']

As you can see that hand contains four of the same rank so that's 1 point for the player. But how would I check if the hand contains four instances of any item in the ranks list? Do I have to iterate through each item in the list or there some clean and simple way to it?


EDIT
Thanks a lot for all the answers guys. :D But I'm getting an attribute error when I try to use 'split' on the items in the hand. Guess I should have posted more of the code I'm running.

Full code and traceback here
http://pastebin.com/TwHkrbED

Is there something wrong with how the methods are defined in Card? I've been hacking around for hours trying to make it work, but no luck.

EDIT2
Made some changes to the deck generating part. Now the whole deck is a list of tuples and a lot less code.

thedeck=[]
class Deckofcards:
    suits = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
    ranks = ['Ace', '2', '3', '4', '5', 
        '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King']
    def __init__(self):
        for i in self.suits:
            for a in self.ranks:
                thedeck.append((i, a))

Seems like the other way was overly complicated, but idk. I'll see how it goes tomorrow, adding the actual game parts.


Solution

  • I might suggest a slight refactoring: Represent each card in a hand as a tuple of (rank, suit). So your example hand would be:

    hand = [('2', 'Clubs'),
            ('king', 'Diamonds'),
            ('2', 'Diamonds'),
            ('2', 'Spades'),
            ('2', 'Hearts')]
    

    Then I'd suggest a couple of auxiliary functions to help you determine the value of a hand:

    from collections import defaultdict
    
    def get_counts(hand):
        """Returns a dict mapping card ranks to counts in the given hand."""
        counts = defaultdict(int)
        for rank, suit in hand:
            counts[rank] += 1
        return counts
    
    def get_points(hand):
        """Returns the number of points (ie, ranks with all 4 cards) in the given
        hand."""
        return sum(1 for count in get_counts(hand).itervalues() if count == 4)
    

    Edit: Switched to using sum in the get_points function, which seems clearer to me.

    Working with these functions and the example hand you gave, you get output like so:

    >>> get_counts(hand)
    defaultdict(<type 'int'>, {'king': 1, '2': 4})
    
    >>> get_points(hand)
    1