[Pythonクイズ]複雑なデータを並べ替える方法、分かりますか?Pythonステップアップクイズ

リストの要素が単純な値ではない場合、それを自分が思った通りの順番に並べ替えるにはちょっとした知識が必要になります。覚えているかどうかを確認してみましょう。

» 2025年02月04日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「Pythonステップアップクイズ」のインデックス

連載目次

ランク順に並べ替えるにはどうする? ランク順に並べ替えるにはどうする?

【問題】

 以下のnames_and_ranksは「名前と何らかのランクの組みからなるタプルを要素とするリスト」である。このリストのsortメソッドを呼び出すと、その名前の順番に並べ替えられる。そうではなく、ランクの昇順に並べ替えたいとしたら、このコードをどのように修正すればよいだろう。

names_and_ranks = [('mike', 5), ('pochi', 2),
                   ('tama', 4), ('kuro', 1),
                   ('shiro', 3)]

names_and_ranks.sort()
print(names_and_ranks)  # そのままだと名前順に並べ替えられる
# 出力結果:
# [('kuro', 1), ('mike', 5), ('pochi', 2),
#  ('shiro', 3), ('tama', 4)]

# 上のコードを修正して、次のようにランク順に並べ替えるにはどうする?
# [('kuro', 1), ('pochi', 2), ('shiro', 3),
#  ('tama', 4), ('mike', 5)]

ランク順に並べ替えるにはどうする?


かわさき

 どうも。HPかわさきです。少し前に公開された編集後記では、Pythonクイズについての熱い(いや、熱くないです)思いを語っているので、「何でクイズなんだよ(笑)」などと最近の連載を見て思ってらっしゃる方は読んでみてください。

 それはさておき、今回はリストの要素の並べ替えがテーマです。今回も分かっている人にはカンタンな問題かもしれませんね。そういう人が考えるだろう答えが今回の正解例なわけですが、やっぱり正解は1つじゃないんですよねぇ。「こんなことやらないでしょ」ってコードも後で紹介します。あー、Pythonでクイズなんかやるんじゃなかった(とは思っていませんよ)。


【答え】

 正解のコード例を以下に示します。

names_and_ranks = [('mike', 5), ('pochi', 2),
                   ('tama', 4), ('kuro', 1),
                   ('shiro', 3)]

# タプルの第1要素(ランク)を選択するラムダ式をkeyパラメーターに指定
names_and_ranks.sort(key=lambda x: x[1])
print(names_and_ranks)

タプルの第1要素(ランク)を選択するラムダ式をkeyパラメーターに指定

 タプルの第1要素(ランク)を選択するラムダ式を、リストのsortメソッドのkeyパラメーターに与えることで、ランクをキーとして並べ替えを行えます。

ランク順に並べ替えられるようになったよ ランク順に並べ替えられるようになったよ

【解説】

 リストには要素をインプレースで並べ替えるためのsortメソッドがあります。そして、sortメソッドにはkeyパラメーターがあり、このパラメーターに「引数を1個取る関数」を与えることで、並べ替えに使うキーを指定したり、計算したりできます。keyパラメーターを指定しないときには、要素同士の大小関係を小なり演算子「<」で比較した結果によって並べ替えが行われます。


かわさき

 リストのsortメソッドは、呼び出しに使ったリストそのものを変更してしまいます。そうではなく、新しいリストが必要ならPythonに組み込みのsorted関数を使うとよいでしょう。この関数は引数に与えたリスト(などの反復可能オブジェクト)を並べ替えた新しいリストを返すもので、sortメソッドと同じ役割を持つkeyパラメーターがあります。


 keyパラメーターには関数やメソッド、ラムダ式など呼び出し可能で引数を1個取るものを指定します。sortメソッドでは、リストの要素を引数として、keyパラメーターに指定された関数を呼び出し、その関数が返す戻り値を基に並べ替えが実行されます。

 以下のように大文字小文字を含んだ英単語を要素とするリストを、大文字小文字の関係なしにアルファベット順に並べ替えるのはよくある例です。このときには文字列のupperメソッドまたはlowerメソッドをkeyパラメーターに与え、全ての要素を大文字あるいは小文字にそろえることで、大文字小文字の違いを吸収してしまいます。

str_list = ['Foo', 'bAR', 'Baz']
str_list.sort(key=str.lower)  # 全てを小文字化したものを並べ替えのキーとする
print(str_list)  # ['bAR', 'Baz', 'Foo']

全ての単語を小文字化したものをキーとして並べ替え

 問題は「タプルの第1要素(ランク)を基にリストの要素を並べ替えたい」というものでした。そして、タプルから特定の要素を取り出すという関数はPythonには用意されていません。そのため、正解のコード例では、タプルを与えるとその第1要素を返すようなラムダ式をkeyパラメーターに指定しています。これにより、ランクの値をキーとして並べ替えが行われるようになるわけです。


かわさき

 単なる要素の並べ替えではなく、何らかのロジックを基にリストの要素を並べ替えたいときにはkeyパラメーターをうまく使えることを覚えておきましょう。


 これで終わってしまってもよいのですが、例によって「正解は1つじゃない」ことをご紹介しておきましょう。ヘンテコなコードなので、無理にこんなことをする必要はありません。

 コードを紹介する前に一つ。keyパラメーターを指定しない場合は、要素同士を小なり演算子「<」で比較した結果を基に並べ替えが行われます。問題ではリストの要素はタプルなので、この場合はタプル同士の比較が行われるということです。タプル同士の比較では、その第0要素同士が比較され、それが同じなら第1要素同士を比較して、それも同じなら……といった具合に大小関係が決まります。

print((0, 1) == (0, 1))  # True
print((0, 1, 2) == (0, 1, 3))  # False
print((0, 1, 2) < (0, 1, 3))  # True

タプルの各要素を順に比較して大小関係が決まる

 ということは、「(名前, ランク)」というタプルを「(ランク, 名前)」というタプルにすればkeyパラメーターを指定しなくてもランク順に並べ替えられそうです。実際にやってみましょう(ここではsortメソッドではなく、sorted関数を使ってみました。その理由は以下のコードにある「sorted_by_rank = ……」と「result = ……」の2行を1行の内包表記に書き直してみると分かるはずです。興味のある方は書き直してみてください)。

names_and_ranks = [('mike', 5), ('pochi', 2),
                   ('tama', 4), ('kuro', 1),
                   ('shiro', 3)]

sorted_by_rank = sorted((r, n) for n, r in names_and_ranks)
result = [(n, r) for r, n in sorted_by_rank]
print(result)  # 同じ結果

誰もがやらないランク順に並べ替えるコードの例

 まあ、これと同じことはkeyパラメーターに「lambda x: (x[1], x[0])」と書けばできちゃうんですよね。さらにいえば、そう書くくらいなら「lambda x: x[1]」と書くだけでいいじゃんって話になっちゃうのですが……。


かわさき

 こういうコードを考えるのは無駄なことのようにも思えます。が、Pythonについて理解を深めるという観点からは少しは役に立つのかなと筆者は考えています。皆さんも「こんなやり方はどうだろう?」とどんどん考えてみてくださいね。

 sortメソッドとsorted関数については「Python入門」の「リストの操作」で、タプルについては同じく「Python入門」の「タプル」で説明しています。興味のある方はぜひそちらも読んでください。


「Pythonステップアップクイズ」のインデックス

Pythonステップアップクイズ

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。