Reputation: 417
I'm currently stuck on an assignment, where it asks to build a function and rank the suits in a certain order (♢,♣,♡,♠)
My code should end up returning this:
['10♢', '10♣', '10♡', '10♠', '2♢', '2♣', '2♡', '2♠', '3♢', '3♣', '3♡', '3♠', '4♢', '4♣', '4♡', '4♠', '5♢', '5♣', '5♡', '5♠', '6♢', '6♣', '6♡', '6♠', '7♢', '7♣', '7♡', '7♠', '8♢', '8♣', '8♡', '8♠', '9♢', '9♣', '9♡', '9♠', 'A♢', 'A♣', 'A♡', 'A♠', 'J♢', 'J♣', 'J♡', 'J♠', 'K♢', 'K♣', 'K♡', 'K♠', 'Q♢', 'Q♣', 'Q♡', 'Q♠']
Here is my code:
def helper_function(cards):
value = 0
for string in cards:
if '♢' in string:
value = 1
if '♣' in string:
value = 2
if '♡' in string:
value = 3
if '♠' in string:
value = 4
def card_sorter_v1(cards):
return sorted(cards, key = helper_function)
I know I need to use custom comparisons, but I am not sure what else to put in the helper function to sort this deck. I cannot hard-code any values because the testing framework will include edge cases. Any tips or advice?
Here is the output I am currently receiving:
['A♢', '2♢', '3♢', '4♢', '5♢', '6♢', '7♢', '8♢', '9♢', '10♢', 'J♢', 'Q♢', 'K♢', 'A♣', '2♣', '3♣', '4♣', '5♣', '6♣', '7♣', '8♣', '9♣', '10♣', 'J♣', 'Q♣', 'K♣', 'A♡', '2♡', '3♡', '4♡', '5♡', '6♡', '7♡', '8♡', '9♡', '10♡', 'J♡', 'Q♡', 'K♡', '15♡', 'A♠', '2♠', '3♠', '4♠', '5♠', '6♠', '7♠', '8♠', '9♠', '10♠', 'J♠', 'Q♠', 'K♠']
Upvotes: 0
Views: 1012
Reputation: 464
I don't know why this works, but here:
List = ['10♠', '10♡', '10♢', '10♣', '2♠', '2♡', '2♢',
'2♣', '3♠', '3♡', '3♢', '3♣', '4♠', '4♡', '4♢',
'4♣', '5♠', '5♡', '5♢', '5♣', '6♠', '6♡', '6♢',
'6♣', '7♠', '7♡', '7♢', '7♣', '8♠', '8♡', '8♢',
'8♣', '9♠', '9♡', '9♢', '9♣', 'A♠', 'A♡', 'A♢',
'A♣', 'J♠', 'J♡', 'J♢', 'J♣', 'K♠', 'K♡', 'K♢',
'K♣', 'Q♠', 'Q♡', 'Q♢', 'Q♣']
def val(ele):
color = ele[-1]
value = ele.replace(color,'')
ord_color = ['♠','♡','♣','♢']
ord_value = ['Q','K','J','A','9','8','7','6','5','4','3','2','10']
rank = ord_color.index(color) + (ord_value.index(value)*len(ord_color))
return rank
List.sort(key=val,reverse=True)
print(List)
Upvotes: 0
Reputation: 386
here I used two functions, one to sort the deck by numbers, and another to sort it by symbols:
cards = ['10♠', '10♡', '10♢', '10♣', '2♠', '2♡', '2♢', '2♣', '3♠', '3♡', '3♢', '3♣', '4♠', '4♡', '4♢', '4♣', '5♠', '5♡', '5♢', '5♣', '6♠', '6♡', '6♢', '6♣', '7♠', '7♡', '7♢', '7♣', '8♠', '8♡', '8♢', '8♣', '9♠', '9♡', '9♢', '9♣', 'A♠', 'A♡', 'A♢', 'A♣', 'J♠', 'J♡', 'J♢', 'J♣', 'K♠', 'K♡', 'K♢', 'K♣', 'Q♠', 'Q♡', 'Q♢', 'Q♣']
# sorts deck by number
def sort_by_number(cards):
sort = ["10", "2", "3", "4", "5", "6", "7", "8", "9", "A", "J", "K", "Q"]
sorted_deck = []
for i in sort:
for card in cards:
if card[:-1] == i:
sorted_deck.append(card)
return sorted_deck
# sorts deck by symbol:
def sort_by_symbol(cards):
cards = sort_by_number(cards)
for i in range(0, len(cards)):
current_num = cards[i][:-1]
_0, _1, _2, _3 = 0, 0, 0, 0
for card in cards:
if card[:-1] == current_num:
if card[-1] == "♢":
_0 = card
if card[-1] == "♣":
_1 = card
if card[-1] == "♡":
_2 = card
if card[-1] == "♠":
_3 = card
cards[i:i+4] = [_0, _1, _2, _3]
return cards
Upvotes: 0
Reputation: 3401
I did not use a pythonic way to solve it, i just converted each card's rank to a number between 1 and 4, then i've wrote a bubble sort to sort the list :
def convert_card_to_number(card):
if '♢' in card:
return card[:-1]+'1'
if '♣' in card:
return card[:-1]+'2'
if '♡' in card:
return card[:-1]+'3'
if '♠' in card:
return card[:-1]+'4'
cards = ['10♠', '10♡', '10♢', '10♣', '2♠', '2♡', '2♢', '2♣', '3♠', '3♡', '3♢', '3♣', '4♠', '4♡', '4♢', '4♣', '5♠', '5♡', '5♢', '5♣', '6♠', '6♡', '6♢', '6♣', '7♠', '7♡', '7♢', '7♣', '8♠', '8♡', '8♢', '8♣', '9♠', '9♡', '9♢', '9♣', 'A♠', 'A♡', 'A♢', 'A♣', 'J♠', 'J♡', 'J♢', 'J♣', 'K♠', 'K♡', 'K♢', 'K♣', 'Q♠', 'Q♡', 'Q♢', 'Q♣']
for i in range(len(cards)):
for j in range(i+1,len(cards)):
if convert_card_to_number(cards[i])>convert_card_to_number(cards[j]):
temp = cards[i]
cards[i] = cards[j]
cards[j] = temp
print(cards)
the output would be :
['10♢', '10♣', '10♡', '10♠', '2♢', '2♣', '2♡', '2♠', '3♢', '3♣', '3♡', '3♠', '4♢',
'4♣', '4♡', '4♠', '5♢', '5♣', '5♡', '5♠', '6♢', '6♣', '6♡', '6♠', '7♢', '7♣', '7♡',
'7♠', '8♢', '8♣', '8♡', '8♠', '9♢', '9♣', '9♡', '9♠', 'A♢', 'A♣', 'A♡', 'A♠', 'J♢',
'J♣', 'J♡', 'J♠', 'K♢', 'K♣', 'K♡', 'K♠', 'Q♢', 'Q♣', 'Q♡', 'Q♠']
Upvotes: 0
Reputation: 30240
Here's one approach:
cards = ['10♠', '10♡', '10♢', '10♣', '2♠', '2♡', '2♢', '2♣', '3♠', '3♡', '3♢', '3♣', '4♠', '4♡', '4♢', '4♣', '5♠', '5♡', '5♢', '5♣', '6♠', '6♡', '6♢', '6♣', '7♠', '7♡', '7♢', '7♣', '8♠', '8♡', '8♢', '8♣', '9♠', '9♡', '9♢', '9♣', 'A♠', 'A♡', 'A♢', 'A♣', 'J♠', 'J♡', 'J♢', 'J♣', 'K♠', 'K♡', 'K♢', 'K♣', 'Q♠', 'Q♡', 'Q♢', 'Q♣']
SUIT_ORDER = {
'♢': 0,
'♣': 1,
'♡': 2,
'♠': 3,
}
RANK_ORDER = {str(r):r for r in range(2,11)}
RANK_ORDER.update(
J = 11,
Q = 12,
K = 13,
A = 14,
)
def helper(card):
suit = SUIT_ORDER.get(card[-1:], 20)
rank = RANK_ORDER.get(card[:-1], 20)
return (suit, rank)
cards.sort(key=helper)
print(cards)
This uses dictionaries as mappings from either suit symbol or rank (as a string) to turn a card string into a 2-tuple of ("suit score", "rank score").
The helper function returns this tuple and sort uses the helper function as a sort key.
Results:
[ '2♢', '3♢', '4♢', '5♢', '6♢', '7♢', '8♢', '9♢', '10♢', 'J♢', 'Q♢', 'K♢', 'A♢', '2♣', '3♣', '4♣', '5♣', '6♣', '7♣', '8♣', '9♣', '10♣', 'J♣', 'Q♣', 'K♣', 'A♣', '2♡', '3♡', '4♡', '5♡', '6♡', '7♡', '8♡', '9♡', '10♡', 'J♡', 'Q♡', 'K♡', 'A♡', '2♠', '3♠', '4♠', '5♠', '6♠', '7♠', '8♠', '9♠', '10♠', 'J♠', 'Q♠', 'K♠', 'A♠' ]
Edit:
I changed the default of the get
calls to 20, a number higher than any valid card. You don't need to do this (and could simply use RANK_ORDER[card[-1:]]
) but this way your program will still function with invalid suits or ranks, and the sort will place them at the end.
(Using []
indexing would result in a KeyError
for invalid cards and .get()
with the default default of None
would result in a TypeError
when you went to sort.)
Edit 2:
My code should end up returning this: ['10♢', '10♣', '10♡', '10♠', '2♢', '2♣', '2♡', '2♠', '3♢', '3♣', '3♡', '3♠', '4♢', '4♣', '4♡', '4♠', '5♢', '5♣', '5♡', '5♠', '6♢', '6♣', '6♡', '6♠', '7♢', '7♣', '7♡', '7♠', '8♢', '8♣', '8♡', '8♠', '9♢', '9♣', '9♡', '9♠', 'A♢', 'A♣', 'A♡', 'A♠', 'J♢', 'J♣', 'J♡', 'J♠', 'K♢', 'K♣', 'K♡', 'K♠', 'Q♢', 'Q♣', 'Q♡', 'Q♠']
If that's what you really want, your key function can be a lot simpler:
def helper(card):
suit = SUIT_ORDER.get(card[-1:], 20)
rank = card[:-1]
return (rank, suit)
Upvotes: 1
Reputation: 247
You can use string slicing to break up the card and suit:
for card in cards:
(card[:-1], card[-1])
The first element of the tuple is the card; the second element is the suit. I recommend making helper functions for both. I see you are already doing that for the suit, but you will also need it for the card to deal with the picture cards.
Then check out this answer to see how to sort a list of tuples: How does operator.itemgetter and sort() work in Python?
Upvotes: 0