【Python 雑談・雑学 + coding challenge】sorted 組み込み関数の key パラメータをうまく使って、カスタムオブジェクトを簡単にソートしよう! __getitem__、__len__ 特殊関数 ( special methods, dunder methods ) を実装すれば立派なシーケンス ( sequence ) です 投稿一覧へ戻る
Published 2020年8月29日7:09 by mootaro23
SUPPORT UKRAINE
- Your indifference to the act of cruelty can thrive rogue nations like Russia -
唐突に coding challenge です!
さて、いかがだったでしょか?
様々な方法があると思います。
今回は Python の sorted() 組み込み関数の key パラメータに、並べ替えのための比較値を提供する自作関数を渡す、という方法で実装してみました。
気付いたでしょうか? 実は、Deck クラスの ranks リスト、suits リストとも弱い順に並んでいるんです。
ここではそれをフルに活用しています。
これだけです。
問題: トランプをソート ( sort ) してください。 ( 制限時間: 25 分 )
ナナさんはトランプを 1 組持っています ( Deck クラスオブジェクト )。
妹にグチャグチャにシャッフルされてしまって途方に暮れています。
どうぞカードをソートしてあげてください。
カードの rank は 2, 3, ..., 9, 10, J, Q, K, A の順に強くなり、
カードの suit は clubs, diamonds, hearts, spades の順に強くなります。
ではお願いします (ペコリ)。
ナナさんはトランプを 1 組持っています ( Deck クラスオブジェクト )。
妹にグチャグチャにシャッフルされてしまって途方に暮れています。
どうぞカードをソートしてあげてください。
カードの rank は 2, 3, ..., 9, 10, J, Q, K, A の順に強くなり、
カードの suit は clubs, diamonds, hearts, spades の順に強くなります。
ではお願いします (ペコリ)。
from collections import namedtuple
from random import shuffle
Card = namedtuple('Card', ['rank', 'suit'])
class Deck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'clubs diamonds hearts spades'.split()
def __init__(self):
self.cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self.cards)
def __getitem__(self, pos):
return self.cards[pos]
def __setitem__(self, pos, value):
self.cards[pos] = value
deck = Deck()
shuffle(deck) # 妹よ、何ということを ...
sorted_deck = ソート関数(deck) # この部分を作成してください
print(sorted_deck[:5])
# [Card(rank='2', suit='clubs'), Card(rank='2', suit='diamonds'), Card(rank='2', suit='hearts'), Card(rank='2', suit='spades'), Card(rank='3', suit='clubs')]
print(sorted_deck[-5:])
# [Card(rank='K', suit='spades'), Card(rank='A', suit='clubs'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='hearts'), Card(rank='A', suit='spades')]
from random import shuffle
Card = namedtuple('Card', ['rank', 'suit'])
class Deck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'clubs diamonds hearts spades'.split()
def __init__(self):
self.cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self.cards)
def __getitem__(self, pos):
return self.cards[pos]
def __setitem__(self, pos, value):
self.cards[pos] = value
deck = Deck()
shuffle(deck) # 妹よ、何ということを ...
sorted_deck = ソート関数(deck) # この部分を作成してください
print(sorted_deck[:5])
# [Card(rank='2', suit='clubs'), Card(rank='2', suit='diamonds'), Card(rank='2', suit='hearts'), Card(rank='2', suit='spades'), Card(rank='3', suit='clubs')]
print(sorted_deck[-5:])
# [Card(rank='K', suit='spades'), Card(rank='A', suit='clubs'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='hearts'), Card(rank='A', suit='spades')]
さて、いかがだったでしょか?
様々な方法があると思います。
今回は Python の sorted() 組み込み関数の key パラメータに、並べ替えのための比較値を提供する自作関数を渡す、という方法で実装してみました。
気付いたでしょうか? 実は、Deck クラスの ranks リスト、suits リストとも弱い順に並んでいるんです。
ここではそれをフルに活用しています。
def sort_deck(card: Card):
"""
Deck オブジェクトをソートする際の比較値を提供する
:param card: Card型
:return: 並べ替え時の比較値となる int 値
"""
rank_value = Deck.ranks.index(card.rank) # カードの数字ごとの強さを表す数値としてリストのインデックス番号を割り当てます
return rank_value * len(Deck.suits) + Deck.suits.index(card.suit) # カードのマークの強さを表す数値としてリストのインデックス番号を利用します
sorted_deck = sorted(deck, key=sort_deck)
"""
Deck オブジェクトをソートする際の比較値を提供する
:param card: Card型
:return: 並べ替え時の比較値となる int 値
"""
rank_value = Deck.ranks.index(card.rank) # カードの数字ごとの強さを表す数値としてリストのインデックス番号を割り当てます
return rank_value * len(Deck.suits) + Deck.suits.index(card.suit) # カードのマークの強さを表す数値としてリストのインデックス番号を利用します
sorted_deck = sorted(deck, key=sort_deck)
これだけです。
deck = Deck()
shuffle(deck)
print(deck[:5])
# [Card(rank='10', suit='spades'), Card(rank='2', suit='clubs'), Card(rank='10', suit='hearts'), Card(rank='6', suit='spades'), Card(rank='J', suit='spades')]
print(deck[-5:])
# [Card(rank='K', suit='diamonds'), Card(rank='5', suit='clubs'), Card(rank='9', suit='diamonds'), Card(rank='8', suit='spades'), Card(rank='Q', suit='spades')]
sorted_deck = sorted(deck, key=sort_deck)
print(sorted_deck[:5])
# [Card(rank='2', suit='clubs'), Card(rank='2', suit='diamonds'), Card(rank='2', suit='hearts'), Card(rank='2', suit='spades'), Card(rank='3', suit='clubs')]
print(sorted_deck[-5:])
# [Card(rank='K', suit='spades'), Card(rank='A', suit='clubs'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='hearts'), Card(rank='A', suit='spades')]
shuffle(deck)
print(deck[:5])
# [Card(rank='10', suit='spades'), Card(rank='2', suit='clubs'), Card(rank='10', suit='hearts'), Card(rank='6', suit='spades'), Card(rank='J', suit='spades')]
print(deck[-5:])
# [Card(rank='K', suit='diamonds'), Card(rank='5', suit='clubs'), Card(rank='9', suit='diamonds'), Card(rank='8', suit='spades'), Card(rank='Q', suit='spades')]
sorted_deck = sorted(deck, key=sort_deck)
print(sorted_deck[:5])
# [Card(rank='2', suit='clubs'), Card(rank='2', suit='diamonds'), Card(rank='2', suit='hearts'), Card(rank='2', suit='spades'), Card(rank='3', suit='clubs')]
print(sorted_deck[-5:])
# [Card(rank='K', suit='spades'), Card(rank='A', suit='clubs'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='hearts'), Card(rank='A', suit='spades')]
この記事に興味のある方は次の記事にも関心を持っているようです...
- People who read this article may also be interested in following articles ... -