# Q：检查多个列表中的字符串

I'm trying to find out if the following poker hand is a flush:

In the first case I analyse 5 cards. A flush is true if there all the 5 suits are identical (C H D S), i.e. there is only one suit present. That works fine.

a=['AC', '3H', 'TD', '9C', 'KD']
flush = len({suit for _, suit in a}) ==1 #false

In reality however there are usually 7 cards. 2 are held by the player and 5 are on the table. Here it gets a bit more complicated. How can I check if any suit occurs exactly 5 times?

b=['AC', '3H', 'TD', '9C', 'KD', '7H', '5S']
flush = ?

Speed is very important as this is part of an inner loop of a montecarlo simulation, so this should probably be a one-liner if possible.

a=['AC', '3H', 'TD', '9C', 'KD']
flush = len({suit for _, suit in a}) ==1 #false

b=['AC', '3H', 'TD', '9C', 'KD', '7H', '5S']
flush = ?

You could use count and max to find... well, the max count of any of the suits and see whether it's at least 5.

>>> b = ['AC', '3H', 'TD', '9C', 'KD', '7H', '5S']
>>> suits = [s for _, s in b]
>>> max(suits.count(s) for s in suits) >= 5
False

But this will loop the list of suits for each element of that list, giving it O(n^2) complexity. Probably not too bad, considering that n is just 7, but still. Or use collections.Counter. This should be much faster (O(n)), as it uses a dictionary to keep track of the counts.

>>> max(collections.Counter((s for _, s in b)).values())
2
>>> collections.Counter((s for _, s in b)).most_common(1)
[('H', 2)]

>>> b = ['AC', '3H', 'TD', '9C', 'KD', '7H', '5S']
>>> suits = [s for _, s in b]
>>> max(suits.count(s) for s in suits) >= 5
False

>>> max(collections.Counter((s for _, s in b)).values())
2
>>> collections.Counter((s for _, s in b)).most_common(1)
[('H', 2)]
list = ['AC', '3H', 'TD', '9C', 'KD']
substring='C'
print( len([s for s in list if substring in s]))
list = ['AC', '3H', 'TD', '9C', 'KD']
substring='C'
print( len([s for s in list if substring in s]))

If speed is the key, well, there are only 7 cards, 4 suits. That makes 16384 combinations. I would convert each combination to a number and make a lookup in a precomputed table using this number as an index.

CONV = dict(C=0, H=1, D=2, S=3)
def flush_table_index(cards):
n = 0
for _, s in cards:
n = n * 4 + CONV[s]
return n

Edit: if-elif-elif instead of CONV would be quicker. Not a pretty or interesting code though.

CONV = dict(C=0, H=1, D=2, S=3)
def flush_table_index(cards):
n = 0
for _, s in cards:
n = n * 4 + CONV[s]
return n

string  list  python-3.x  poker