配列をユニークにしてその個数を返せ
ちょっと古い記事だけど、ζ*’ワ’)ζ<うっうー遅レス。より
配列をユニークにしてその個数とともに返せ。
具体的には、["foo", "bar", "foo", "baz", "bar", "foo"] を、[ ["foo", 3], ["bar", 2], ["baz", 1] ] にする。
面白いので勉強がてら考えてみます。例はRubyなので、配列を返しているけど、pythonなんでタプルで返すが良さそうですね。
戦略としては、まずリストをユニークな文字列の配列に変換し、ユニークな文字列ごとに数を数えるのが簡単そうです。
ユニークな文字の配列に変換するのは、setを使います。で、リスト内包を使って、タプルを生成してみます。
list=["foo", "bar", "foo", "baz", "bar", "foo"] [(x, list.count(x)) for x in set(list)]
こんな結果になりました。
[('baz', 1), ('foo', 3), ('bar', 2)]
あれ?ちょっと結果が期待するものと違いますね。結果をソートしてないからですね。
list=["foo", "bar", "foo", "baz", "bar", "foo"] sorted([(x, list.count(x)) for x in set(list)], cmp=lambda x,y:cmp(x[1],y[1]),reverse=True)
[('foo', 3), ('bar', 2), ('baz', 1)]
できた!
だけどちょっとコードが長いなあ。
listを何度もカウントしているところが、微妙にコストが高い気がしますが、まあオンメモリなんでたいしてコストはかからんでしょう。1行にまとめられると綺麗なんだけど、やりかたがよくわかりませんでした。まだまだ修行が足りないなあ。
ソートをリスト内包の直後に実行しようと、Noneが返ってくるのも謎。演算子の順番なのかしら?
[(x, list.count(x)) for x in set(list)].sort(cmp=lambda x,y:cmp(x[1],y[1]),reverse=True)
実行結果
None
なぜ?
pythonはリスト内包が強力ですね。最初は全然わからなかったけど、慣れてくるとリスト内包も楽しいな。