1

In my Rummy program I have to order the output so that the cards are printed with high to low value (K being the highest, A being the lowest) for example:

input: 1. 8H, 8C, 8S, 2C, 7S, 9H, KD

output: 1. 8S, 8H, 8C, KD, 9C, 7H, 2C

run4 = []
set4 = []
run3 = []
set3 = []
other = []
cards = input('1. ')
cards = cards.split(', ')
card_numbers_count = {'A':0, '2':0, '3':0, '4':0, '5':0, '6':0, '7':0, '8':0, '9':0, 'T':0, 'J':0, 'Q':0, 'K':0}
card_suit_count = {'H':0, 'D':0, 'S':0, 'C':0}

def card_suit_key(card):
    suit_vals = {'S': 1, 'H': 2, 'C': 3, 'D': 4}
    return suit_vals[card[1]]
def numerical_order(card):
    num_vals = {'K': 1, 'Q': 2, 'J': 3, 'T': 4, '9': 5, '8': 6, '7': 7, '6': 8, '5': 9, '4': 10, '3': 11, '2': 12, 'A': 13}
    return num_vals[card[1]]

# card value
for card in cards:
    card_number = card[:-1]
    card_numbers_count[card_number] += 1
for card in cards:
    card_number = card[:-1]
    if card_numbers_count[card_number] == 3:
        run3.append(card)
        run3.sort(key=card_suit_key)
    elif card_numbers_count[card_number] == 4:
        run4.append(card)
        run4.sort(key=card_suit_key)
    elif card_numbers_count[card_number] > 3 or card_numbers_count[card_number] < 3:
        other.append(card)
        print (other)
        #other.sort(key=numerical_order)
print (run4, run3, other)

# card suit
for card in cards:
    card_suit  = card[1:]
    card_suit_count[card_suit] += 1
for card in cards:
    card_suit  = card[1:]

I have edited the question because I was able to do it for ordering the suits from highest to lowest but I am not able to do the same for card value. Any help would be appreciated. Thanks.

zara
  • 375
  • 1
  • 4
  • 18

3 Answers3

2

I'm not quite sure how you're sorting your example, but if you want to sort cards by their suit (spades, hearts, clubs, diamonds), you could make a custom key function. You could hold the "weight" of each suit in a dictionary like this:

Edit: Here's a simplified version that can do both sorts at once, by returning a tuple in the key function:

>>> cards = ['8H', '8C', '8S', '2C', '7S', '9H', 'KD']
>>>
>>> def card_suit_key(card):
...     suits = 'S H C D'.split()
...     ranks = 'K Q J 10 9 8 7 6 5 4 3 2 A'.split()
...     return (suits.index(card[-1]), ranks.index(card[:-1]))
...
>>> cards.sort(key=card_suit_key)
>>> cards
['8S', '7S', '9H', '8H', '8C', '2C', 'KD']
Nitzle
  • 2,417
  • 2
  • 22
  • 23
  • I tried using the same technique to sort: '2C','7S','9H,'KD' into 'KD', '9H, '7S', '2C'. I am not trying to reverse the order, I'm trying to order the remaining cards in highest to lowest (K being the highest, A being the lowest) but it seems not to work D: – zara Apr 07 '13 at 19:49
  • @Icecream see my revised answer. Hopefully it should fix the problem. – Nitzle Apr 07 '13 at 20:37
  • @Icecream Also note that I changed the key function to use `card[-1]` so it can handle the '10' card properly, and the secondary sorting to use `x[:-1]` instead for the same purpose. – Nitzle Apr 07 '13 at 20:46
  • 1
    Consider having your key function return a `tuple`. Then you can do the sort in a single step. – John La Rooy Apr 08 '13 at 02:40
  • @gnibbler Good point... changes made. Should be a lot simpler now. – Nitzle Apr 08 '13 at 14:24
2

Sorting via a simple lookup-table would be fairly fast, and if you make creation of that table data-driven, as shown below, the whole thing would be very easy to change when necessary -- just reorder the values in the RANKS and/or SUITS list(s) as desired.

from itertools import product

RANKS = 'A 2 3 4 5 6 7 8 9 10 J Q K'.split()  # low to high value
SUITS = 'S H C D'.split()  # high to low suit
DECK = list(''.join(it) for it in product(RANKS, SUITS))
LUT = dict((card, index) for index,card in enumerate(DECK))

hand = ['8H', '8C', '8S', '9C', '7S', '9H', 'KD']
print sorted(hand, key=LUT.get)

Output:

['7S', '8S', '8H', '8C', '9H', '9C', 'KD']
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    can also just use `key=LUT.get` – John La Rooy Apr 08 '13 at 01:41
  • `LUT = dict((card, idx) for idx, card in enumerate(DECK))` is a little more efficient. DECK could be created by a list comprehension – John La Rooy Apr 08 '13 at 01:43
  • @gnibbler: Both good points, thanks, although the second is optimizing initialization which hopefully will only be done once (but it's more clear, too). – martineau Apr 08 '13 at 01:55
  • @gnibbler: A subtle side-effect of changing the `key=lambda card: LUT[card]` to `key=LUT.get` is that it causes invalid card names to be silently ignored instead of them raising a `KeyError`. – martineau Apr 08 '13 at 12:14
1

Store it in a temporary array/list in the correct order, then copy it back to the original array/list.

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75