Min and Max (Home) - min,max関数を実装
またまたHome島に新しい問題が追加されていた。
どんな問題?
Min and Max
http://www.checkio.org/mission/min-max/
ビルトインのmin(),max()関数を実装せよ。
ただし、import, eval, exec, globalsは使ってはならない。
オプションのkey引数にも対応させること。
ビルトインのmin/maxのように、複数の引数だったり、リスト、文字列、ジェネレータなどが渡される。
オプション引数のkeyが指定される場合もある。
例題:
max(3, 2) == 3 min(3, 2) == 2 max([1, 2, 0, 3, 4]) == 4 min("hello") == "e" max(2.2, 5.6, 5.9, key=int) == 5.6 min([[1,2], [3, 4], [9, 0]], key=lambda x: x[1]) == [9, 0]
どうやって解く?
オプションのkey引数は、デフォルトでNoneなので、Noneなら値をそのまま返すように、
if key is None: key = labmda x: x
としておいた。
また、argsは可変長引数なので、引数が一つなら args[0]に複数の要素が入っていると考える。
あとは、要素を1つ1つ比較して最大値または最小値を求める。
minとmaxでは、要素の比較部分だけが違うので、比較用の関数をlambda式で渡すようにする。
def min_or_max(args, key, func): if key is None: key = lambda x: x if len(args) == 1: args = args[0] result = None for arg in args: if result is None: result = arg elif func(key(arg), key(result)): result = arg return result def min(*args, key=None): return min_or_max(args, key, lambda a, b: a.__lt__(b)) def max(*args, key=None): return min_or_max(args, key, lambda a, b: a.__gt__(b))
http://www.checkio.org/mission/min-max/publications/natsuki/python-3/first/
あっ、a.__lt__(b) のところは、a < b でいいのに。なんで__lt__を使ったんだろう??? orz
他の人の答え
sortを使うとか、iterを使うとか、いろいろな解答があって面白い。
気になったのが、こちらのコメント欄でのやりとり。
http://www.checkio.org/mission/min-max/publications/Sim0000/python-3/first/
ようするに、1つの要素に対して、key(~) を何度も呼び出すのは良くないという内容。私の書いたコードでも、key(result)は何度も呼び出されるので、以下のテストを試すと AssertionError となってしまう。
x = iter([1,2,3]) y = iter([4,5,6]) z = iter([7,8,9]) least = min(x, y, z, key=next) assert len(list(x)) == 2 assert len(list(y)) == 2 assert len(list(z)) == 2
これを避けるには、1つの要素につき、key(~) を1度しか使わないようにすればいい。書き直してみた。
def min_or_max(args, key, func): if key is None: key = lambda x: x if len(args) == 1: args = args[0] result_key = None for arg in args: arg_key = key(arg) if result_key is None or func(arg_key, result_key): result, result_key = arg, arg_key return result def min(*args, key=None): return min_or_max(args, key, lambda a, b: a < b) def max(*args, key=None): return min_or_max(args, key, lambda a, b: a > b)