简体   繁体   中英

Sort Python list by dict key,value

I have a dictionary of card ranks and values and I want to sort a list of 4 cards so that cards will be appropriately ordered based on rank AND value.

RANKS = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
VALUES = [1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 10, 10, 10]
val_dict = dict(zip(RANKS, VALUES))


list = ["2","2","3","A"] # should sort to ["A",2,2,3]
list2 = ["10","K","J","Q"] # sort to [10,"J","Q","K"]

Background: I am wanting to sort these lists in this manner in order to count runs in a cribbage hand. I use the card's ordinal values to determine if they are sequential. (I could provide that code as well if it might help to re-do that)

You've pretty much got it, you just need to utilise the val_dict you define:

RANKS = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
VALUES = [1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 10, 10, 10]
val_dict = dict(zip(RANKS, VALUES))

Now just add to your code above something that uses val_dict to look up the ranking for a value... eg:

mylist = ["2","2","3","A"] # should sort to ["A",2,2,3]
mylist_sorted = sorted(mylist, key=val_dict.get)
# ['A', '2', '2', '3']

As @Ashwini correctly points out, this won't result in the desired order as per your second example. A fairly simple way around this to keep the logic simple is to change the values:

VALUES = [[1], [2], [3], [4], [5], [6], [7], [8], [9] , [10, 1], [10, 2], [10, 3], [10, 4]]

Assuming your lists are consistent (ie ['2', '2', '3', 'A'] ) and consist of elements of RANKS , ordering by position in RANKS is sufficient :

>>> sorted(['2', '2', '3', 'A'], key=lambda x: RANKS.index(x))
['A', '2', '2', '3']
>>> sorted(['10',"K","J","Q"], key=lambda x: RANKS.index(x))
['10', 'J', 'Q', 'K']

Edit

Alternatively, you can use

val_dict = dict(zip(RANKS, zip(VALUES, range(len(VALUES)))))

which create a dict that associates the RANK name with its value and its index. You can then simply sort using

sorted(myList, key=val_dict.get)

as suggested several times.

Edit (again)

Following the same idea, but much simpler, the actual rank of a card can be put in a dict such as this one

{k: v for v, k in enumerate(RANKS)}

for faster lookup. Identically, the value can be put in another dict for fast lookup :

{RANKS[v]: k for v, k in enumerate(VALUES)}
>>> VALUES = range(len(RANKS))
>>> val_dict = dict(zip(RANKS, VALUES))
>>> sorted([2,2,3,"A"], key=lambda x:val_dict[str(x)])
['A', 2, 2, 3]
>>> sorted([10,"K","J","Q"], key=lambda x:val_dict[str(x)])
[10, 'J', 'Q', 'K']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM