sorting list of cards

最后都变了- 提交于 2021-02-07 11:00:51

问题


I have two lists:

card_candidates = ['9D', '9S', '3S', '0D']
card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']

I want to be able to sort the first list with respect to the second lists order. So the sorted card_candidates should look like this:

sorted_candidates = ['3S', '9D', '9S', '0D']

The '0' is just the value of 10, just wanted to make all the cards the same length. If there is a tie, like with '9D' and '9S', then the letters will need to be sorted instead. So far I have just done this:

sorted_candidates = []
for x, y in zip(card_candidates, card_order):
    sorted_candidates.append([x[0] for x in card_candidates])
return sorted(sorted_candidates)

I know that this is not even close to being right, I just don't know how to do this.


回答1:


Produce a dictionary mapping your sort order characters to a number, we'll sort by those:

sort_map = {c: i for i, c in enumerate(card_order)}

You can now use this mapping to sort your cards, including the second letter to break ties:

sorted_candidates = sorted(card_candidates,
                           key=lambda card: (sort_map[card[0]], card[1]))

The sort key takes the first character of each card and translates that to an integer from the sort_map dictionary, which then inform the sorted() function of the correct sort order. In case of a tie (equal card value), cards are sorted in clubs, diamonds, hearts, spades order (assuming you use C and H for clubs and hearts).

Creating a mapping up front keeps the sort within O(NlogN) time complexity; you could do the same with card_order.index(card[0]), but then you invoke a list.index() call for every sorted element, and list.index needs to scan the list, producing a O(KNlogN) sort (where K is the length of the card_order list).

Demo:

>>> card_candidates = ['9D', '9S', '3S', '0D']
>>> card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']
>>> sort_map = {c: i for i, c in enumerate(card_order)}
>>> sorted(card_candidates, key=lambda card: (sort_map[card[0]], card[1]))
['3S', '9D', '9S', '0D']
>>> sorted(['9D', '9S', '9C', '9H'], key=lambda card: (sort_map[card[0]], card[1]))
['9C', '9D', '9H', '9S']



回答2:


You don't necessarily need any additional data structures, the card_order list is totally enough to sort your cards using this simple one-liner:

card_candidates = ['9D', '9S', '3S', '0D']
card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']

sorted_cards = sorted(card_candidates, key=lambda c: (card_order.index(c[0]), c[1]))

print(list(sorted_cards))

Output:

['3S', '9D', '9S', '0D']

See this code running on ideone.com

Please note that this approach scans the card_order list once for every card to sort each time you sort any card list. This is no problem if you just sort a normal deck of cards at the beginning of a game or even every few seconds. However, if your code is sorting huge numbers of cards or sorting cards most of its time, you might want to prefer the solution by Martijn Pieters which converts the card_order list into a dictionary that can be scanned faster.



来源:https://stackoverflow.com/questions/37179737/sorting-list-of-cards

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!