Dan
Dan

Reputation: 19

How to find if a list contains multiple of the same element in python?

so I just started learning python and I get mini-lessons from my friend every week. This week was to make a simple slot machine game. There are 6 items in the slot machine, and when 3 or more of the same item show up, the user wins. I've tried the below code:

for i in slotScreen:
    if slotScreen.count(i) == 3:
        print('You got 3 of the same! You win!')

The code works when the first item in the list is part of the 3 of a kind, but the code doesn't work if none of the three elements are first on the list, like below:

slotScreen = ['lemon', 'cherry', 'lemon', 'lemon', 'pirate', 'bar']  # works

slotScreen = ['cherry', 'lemon', 'lemon', 'lemon', 'pirate', 'bar']  # not work

Any idea why this happens?

EDIT: More code. I get the You Lose message when I should be getting the You win 3x message.

        for i in slotScreen:
            if slotScreen.count(i) == 6:
                print('You win 10x your bet!!!')
                x = x + int(bet) * 10
                break

            elif slotScreen.count(i) == 5:
                print('You win 5x your bet!')
                x = x + int(bet) * 5
                break

            elif slotScreen.count(i) == 4:
                print('You win 4x your bet!')
                x = x + int(bet) * 4
                break

            elif slotScreen.count(i) == 3:
                print('You win 3x your bet!')
                x = x + int(bet) * 3
                break

            elif slotScreen.count(i) <= 2:
                print('Sorry you lose')
                break

Upvotes: 1

Views: 4835

Answers (6)

0 _
0 _

Reputation: 11464

You could try converting to a set, then comparing:

def main():
    a = [1, 1]
    b = [1, 2]
    print(contains_multiple(a))  # `True`
    print(contains_multiple(b))  # `False`


def contains_multiple(x):
    """Return `True` if `x` contains multiplicates."""
    return len(x) != len(set(x))


if __name__ == '__main__':
    main()

To avoid errors when a list contains some unhashable item, use:

from collections.abc import Hashable


def contains_multiple(x):
    """Return `True` if `x` contains multiplicates."""
    return len(x) != len(unique(x))


def unique(iterable):
    """Return `list` of unique items in `iterable`."""
    if all(is_hashable(x) for x in iterable):
        return set(list(iterable))
    unique = list()
    for item in iterable:
        if item in iterable:
            continue
        unique.append(item)
    return unique


def is_hashable(x):
    """Return `True` if `x` is hashable."""
    return isinstance(x, Hashable)

Upvotes: 0

dansalmo
dansalmo

Reputation: 11686

Use a dict comprehension to make a histogram, then check it.

>>> L = ['cherry', 'lemon', 'lemon', 'bar', 'bar', 'bar']
>>> d = {f: L.count(f) for f in set(L)}
>>> for fruit in d:
        if d[fruit] > 2:
            print("You got {} {}'s! You win!").format(d[fruit], fruit)

You got 3 bar's! You win!

This code may seem cryptic now, but once you learn to read and understand list and dictionary comprehensions they are much easier to use and less error prone.

Here is the dictionary that is created and then named as d. It has each fruit as a key with a count for the value:

>>> {f: L.count(f) for f in set(L)}
{'cherry': 1, 'lemon': 2, 'bar': 3}

The for loop in python can be used to loop through the keys of the dictionary just as easily as items in a list or any other iterable. You can then use each key to access the count value and test it.

Upvotes: 0

Blckknght
Blckknght

Reputation: 104682

While I think some of the other answers have given an alternative implementation, I think it might be useful to see how your current algorithm could be fixed:

    for i in slotScreen:
        if slotScreen.count(i) == 6:
            print('You win 10x your bet!!!')
            x = x + int(bet) * 10
            break

        elif slotScreen.count(i) == 5:
            print('You win 5x your bet!')
            x = x + int(bet) * 5
            break

        elif slotScreen.count(i) == 4:
            print('You win 4x your bet!')
            x = x + int(bet) * 4
            break

        elif slotScreen.count(i) == 3:
            print('You win 3x your bet!')
            x = x + int(bet) * 3
            break

        # no else clause on the if statement, because we can't tell if you've lost yet

    else:  # this else block is attached to the for, and runs if no break was hit
        print('Sorry you lose')

This uses the somewhat obscure else clause that you can put after a for loop. The else block will be run only if the loop runs to completion, rather than being exited early by a break statement. That means that the "you lose" code only happens after all the values in the list have been checked. Note that you could actually stop earlier, since if you've checked the first 4 values in a six-long list, you can't find any three-of-a-kinds in the last two values.

There are some other minor improvements you can make, such as only running slotScreen.count(i) once per cycle through the loop and saving it to a variable that can be tested by each of the if/elif tests.

Upvotes: 0

kamek
kamek

Reputation: 2440

Marco de Wit's response is correct. I thought I would offer a possible solution.

from collections import Counter

counter = Counter(['cherry', 'lemon', 'lemon', 'lemon', 'pirate', 'bar'])
symbol, count = counter.most_common(1)[0]

This will give you the symbol (in this case, 'lemon') and its count (in this case, 3) of the most common symbol in the list (if you want to deal with ties, you'll need to extend this).

Upvotes: 3

Marco de Wit
Marco de Wit

Reputation: 2804

Your program always does break in the first for iteration, so it only evaluates the first element of the list.

Upvotes: 4

Amber
Amber

Reputation: 526523

Your code works for me: http://ideone.com/CKNZb

Upvotes: 1

Related Questions