
【Python 雑談・雑学 + coding challenge】sorted 組み込み関数の key パラメータをうまく使って、カスタムオブジェクトを簡単にソートしよう! __getitem__、__len__ 特殊関数 ( special methods, dunder methods ) を実装すれば立派なシーケンス ( sequence ) です 投稿一覧へ戻る
Published 2020年8月29日7:09 by T.Tsuyoshi
唐突に 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')]
こちらの投稿にも興味があるかもしれません...
- 【Python 雑談・雑学 + coding challenge】Unicode の正規化処理 ( normalization ) を利用して、diacritical marks ( 発音区別符号 ) を取り除こう! テキスト解析の前処理としても重要です!
- 【Python 雑談・雑学 + coding challenge】文字列中の数字を抜き出して桁区切りをつけよう! 正規表現 (regular expression ) を使うと「えっ!?」っていうくらい簡単ですょ。lookahead と negative lookahead を使います。
- 【Python 雑談・雑学 + coding challenge】Python の pprint 機能を自分で実装してみよう! 自分なりの Pretty Print できちゃいます!!
- 【Python 雑談・雑学 + coding challenge】iterator protocol の実装 --- __iter__ 特殊関数は何を返すべき? イテレータオブジェクト ( iterator object ) なら何でも、そう、generator expression でもOKです!
0 comments
コメントはまだありません。
コメントを追加する(不適切と思われるコメントは削除する場合があります)