『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

sortメソッドで昇順・降順に並び替える

list.sort()

リスト型オブジェクトには、要素を昇順あるいは降順に並び替える sort()メソッド が備わっています。sort はシーケンスの中でリスト型だけが備えるメソッドです。タプルや文字列を並び替えたいときは後述する sorted() 関数を使います(Python の構造をよく理解しているエンジニアにとっては、これは妥当だと判断できるでしょう。sort は明らかな破壊的メソッドであり、イミュータブルなシーケンスであるタプルや文字列にこのようなメソッドが備えられていないのは妥当なことです)。

list.sort(key, reverse)

引数 reverse に False を指定するか省略すると昇順、True を指定すると降順です。

# PYTHON_LIST_SORT

# In[1]

# リストを作成
num1 = [4, 2, 5, 1, 3]

# 昇順に並び替える
num1.sort()

print(num1)
# [1, 2, 3, 4, 5]

# In[2]

# リストを作成
num2 = [4, 2, 5, 1, 3]

# 降順に並び替える
num2.sort(reverse = True)

print(num2)
# [5, 4, 3, 2, 1]

key を指定して並べ替える

今度は二種類のデータが一組となった要素をもつリストを考えてみましょう。例として、惑星の軌道長半径 (AU) と、質量 (1024kg) がペアになった一続きのデータを用意します。ちなみに軌道長半径とは惑星が楕円軌道を描くときの長いほうの半径、大まかにいえば太陽からの距離です。AU は地球の軌道長半径を 1 とした単位です。軌道長半径と質量はタプルの形式 (軌道長半径, 質量) でデータを作り、それぞれのタプルをリストの要素として並べます。初期状態では太陽から近いほうから「水・金・地・火・木・土」の順に並んでいます。これを質量の小さい順に並べることを考えてみます。

sort()メソッドの第1引数 key には関数を指定します。このようなケースでは一般に lambda 式 とよばれる無名関数が使われます。lambda 式についての詳しい解説は別記事に譲りますが、ともかくこのように書けば、タプルの中の好きな要素をキーとして並べ替えることができることを知っておくと色々な場面で応用できます。

# PYTHON_SORT_KEY

# In[1]

# 水星,金星,地球,火星,木星,土星
# (軌道長半径[AU],質量[10**24kg])
planets = [(0.387,0.33),(0.723,4.87),(1,5.97),(1.524,0.942),(5.204,1898),(9.582,568)]

# タプルの2番目の要素(質量)を key に昇順に並び替えます
planets.sort(key = lambda tup: tup[1])

print(planets)
# [(0.387, 0.33), (1.524, 0.942), (0.723, 4.87), (1, 5.97), (9.582, 568), (5.204, 1898)]

2 番目の要素を key にするので、インデックスは 1 であることに注意してください。
lambda 式の変数はタプルであることがわかりやすいように tup としてありますが、この部分はどんな変数名でも構いません。要するに

planets.sort(key = lambda x: x[1])

のように記述すると、タプルの 2 番目の要素をキーに並び替えるということです。

itemgetter() を使って並び替える

lambda 式を使うより、operator モジュールから itemgetter() を呼びだしたほうが、より簡潔なコードでソートを実装できます。

# PYTHON_SORT_ITEMGETTER

# In[1]

# itemgetter関数をインポート
from operator import itemgetter

# 水星,金星,地球,火星,木星,土星
# (軌道長半径[AU],質量[10**24kg])
planets = [(0.387,0.33),(0.723,4.87),(1,5.97),(1.524,0.942),(5.204,1898),(9.582,568)]

# 質量をキーにリストを並べ替える
planets.sort(key = itemgetter(1))

print(planets)
# [(0.387, 0.33), (1.524, 0.942), (0.723, 4.87), (1, 5.97), (9.582, 568), (5.204, 1898)]

上のコードでは itemgetter() の引数でタプルのインデックスを指定しています。

sorted() 関数

sorted()関数 はリストのもつ sort()メソッドによく似た機能をもちますが、リストだけでなく、set やタプル、あるいは文字列なども引数に指定して並び替えることができます。

sorted(iterable, key=None,  reverse=False)

オプション引数 key は上で説明した sort()メソッドと同じように関数を指定しますが、昇順・降順に並び替えるだけなら省略して構いません。reverse に False を指定すると昇順、True を指定すると降順に並び替えます (デフォルトは False)。

文字列のソート

sorted() 関数で文字列を昇順に並び替えてみましょう。アルファベットの昇順とは、a, b, c, d, e, … という並び順のことです。

# PYTHON_ALPHABET_SORT

# In[1]

# 文字列を定義
my_str = "DACEB"

# アルファベットを昇順に並べたリストを作成
my_str = sorted(my_str)

print(my_str)
# ['A', 'B', 'C', 'D', 'E']

sorted() 関数に引き渡したデータはすべて list 型となって戻ってきます。文字列で返してもらうには、join()メソッドでリストの要素を結合します。

# In[2]

# 文字列を定義
my_str = "DACEB"

# アルファベットを昇順に並べたリストを作成
my_str = sorted(my_str)

# リストの要素を再び結合
my_str = ''.join(my_str)

print(my_str)
# ABCDE

このような処理を頻繁に行うのであれば、次のような関数を作っておくと便利です。

# In[3]

# 文字列を昇順・降順に並び替える関数
def str_sort(x, s = False):
    y = sorted(x, reverse = s)
    return ''.join(y)

my_str = "DACEB"

# str_sort 関数を使って降順に並び替えます
my_str = str_sort(my_str, True)

print(my_str)
# EDCBA

str_sort 関数の引数 s は降順にするかどうかのオプション引数で、デフォルトでは False になっています。降順に並び替えたい場合は True を指定します。

タプルのソート

sorted() の引数にタプルを指定しても、やはりリスト型で戻ってきます。

# PYTHON_TUPLE_SORT

# In[1]

# タプルを定義
num_tup = (1, 2, 3, 4, 5)

# タプルの要素を降順に並べ替えたリストを作成
num_list = sorted(num_tup, reverse = True)

print(num_list)
# [5, 4, 3, 2, 1]

タプルを渡して並び替えたうえで、やはりタプルで返してもらうならば、先ほどの文字列の場合と同様にタプル専用の並び替え関数を作っておきます。

# In[2]

# タプルを昇順・降順に並び替える関数
def tup_sort(x, s = False):
    y = sorted(x, reverse = s)
    return tuple(y)

# タプルを定義
num_tup = (1, 2, 3, 4, 5)

# 関数を使ってタプルを降順に並び替えます
num_tup = tup_sort(num_tup, True)

print(num_tup)
# (5, 4, 3, 2, 1)

list.reverse()

list.reverse() はリストの要素を逆順に並び替えるメソッドです。

# PYTHON_LIST_REVERSE

# In[1]

framework = ["Django", "Flask", "Plone", "Bottle"]

# リストの並び順を反転させる
framework.reverse()

print(framework)
# ['Bottle', 'Plone', 'Flask', 'Django']

コメント

  1. tiida より:

    こんばんは.多変数関数を記述する際の記号の順を指定する方法についてご存知でしたら教えてほしいのです.例えば,
    f0= (x-alp)**2 + (y-alp)**2
    とすると,
    (alp-x)**2+(alp-y)**2
    と表示されてしまうのですが,
    (x-alp)**2+(y-alp)**2や,
    (y-alp)**2+(x-alp)**2
    等に指定することは可能でしょうか?

    • BlogCat より:

      う~ん。わからないですね。
      collectなどを試してみたけど、効きませんでした。
      申し訳ないです。

  2. HNaito より:

    下記は誤植と思われますので、ご確認ください。
    記事の目次とタイトルで、sort( )関数 → sorted( )関数
    「list.sort( )」で、後述する sort( )関数 → 後述する sorted( )関数
    「key を指定して並べ替える」で、
    タプルの形式 [ 軌道長半径, 質量 ] → タプルの形式 ( 軌道長半径, 質量 )
    「文字列のソート」で、sort( )メソッドで → sorted( )関数で

  3. あとりえこばと より:

    【AI連載小説】羽村陽子のプログラミング日記(8)

    陽子はsortメソッドに対する理解を深め、次は実際にそれを使って簡単なオリジナル・プログラムを作成することに決めました。彼女のアイディアは、友達とのランチで注文した料理の値段を、アルファベット順にソートして出力するプログラムでした。陽子はターミナルを開き、Pythonの対話モードで以下のようなコードを書き始めました。

    # ランチの料理と値段のリスト
    lunch_menu = {"Curry": 800, "Pasta": 1200, "Salad": 600, "Burger": 1000}
    
    # 料理の名前をアルファベット順にソート
    sorted_dishes = sorted(lunch_menu.keys())
    
    # ソートされた順に料理名と値段を表示
    for dish in sorted_dishes:
        price = lunch_menu[dish]
        print(f"{dish}: {price} yen")

    彼女はこのコードを実行すると、予想通りにランチメニューがアルファベット順にソートされ、各料理の値段が表示されました。彼女は手に汗握りながらプログラムを書き、実行する過程で、自分の手でコードを作り上げた達成感に満たされました。
     
    友達とのランチでこのプログラムを実際に使ってみると、メニューが簡単に確認でき、便利だと好評でした。陽子は笑顔で友達に感謝され、自分のプログラミングのスキル向上による実用的な成果を実感しました。