ページへ戻る

− Links

 印刷 

Python​/ソート のバックアップソース(No.1) :: NJF Wiki

xpwiki:Python/ソート のバックアップソース(No.1)

  Next »[5]
*リストのソート [#k77f259e]

リストの内容を変更する、いわゆる「破壊的」なソートするには、sortメソッドを使います。

 original_list = [2,1,4,3,5]

 original_list.sort()

 print(original_list)

結果

 [1, 2, 3, 4, 5]

リストの内容を変更せず、ソートされたコピーを作成するにはsorted関数を使います。

 original_list = [2,1,4,3,5]

 sorted_list = sorted(original_list)

 print(original_list)
 print(sorted_list)

結果

 [2, 1, 4, 3, 5]
 [1, 2, 3, 4, 5]

*リストを降順でソート [#x7f93b0e]

降順でソートするには引数に「reverse = True」を指定します。

 original_list = [2,1,4,3,5]

 original_list.sort(reverse = True)

 print(original_list)

sorted関数についても同様です。

 original_list = [2,1,4,3,5]

 sorted_list = sorted(original_list, reverse = True)

 print(original_list)
 print(sorted_list)

結果
 [2, 1, 4, 3, 5]
 [5, 4, 3, 2, 1]

*辞書型オブジェクトのキーでソート [#b9df95f9]

sorted関数は他のイテラブルにも使えます。例えば辞書型オブジェクトに使用するとキーを並べ替えたリストが得られます。


 original_dict = {2:"B",4:"D",1:"A",3:"C"}

 sorted_dict_key = sorted(original_dict)

 print(original_dict)
 print(sorted_dict_key)

結果
 {2: 'B', 4: 'D', 1: 'A', 3: 'C'}
 [1, 2, 3, 4]


対応する値を含まないキーだけ並び替えたリストが返ることに違和感があるかも知れませんが、実際にはこのやり方が合理的です。

なぜなら、もとの辞書型オブジェクトとキーを使えば対応する値が簡単にとれるからです。
例えば、上の例で並び替えたキーと対応する値を順番に表示するには以下のようにします。

 for k in sorted_dict_key:
     print("key:%s, value:%s" % (k,original_dict[k]))

結果

 key:1, value:A
 key:2, value:B
 key:3, value:C
 key:4, value:D

**キーでソートするならリストにしない方が良い [#i4a2c52d]

ところで、ネット上でPythonの辞書型オブジェクトのソートを検索すると、なぜか以下のような一度リストになおしてからソートする例が多く出てきます。

 sorted_dict_list = sorted(original_dict.items())

 print(sorted_dict_list)

結果
 [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D')]

このやり方はあまりよくありません。

なぜなら、もとの辞書型オブジェクトの中と並べ替えたリストの中に同じ値が含まれており、データが二重化してしまうからです。

この方法では、メモリを無駄に消費するのはもちろん、ソートしてからキーに対応した値を変更しようとすると、並び替えたリスト(sorted_dict_list)と、もとの辞書型オブジェクト(original_dict)の値の両方を変更する必要が出てきます。

しかもリストの方は中がタプルのため値が変更できません。

そのため、もとの辞書型オブジェクトの値を変更した上で、キーでもう一度並べ替えをやりなおすか、タプルをリストに変換してキーを検索して値を変更する、といった処理が必要となります。

並べ替えたキーだけ保持する方法なら、もとの辞書型オブジェクトを変更するだけで良く、そのような処理は必要ありません。

ただし、キーではなく対応する値の方で並べ替えるなら一度リスト化する必要があります。

*並び替えに細かな条件を指定する [#a928baaf]

sorted関数やリストのsortメソッドには「key」という引数があり、これを指定すると細かな並び替え条件を指定できます。

例えば、次のようなリストの並び替えを考えます。


 original_list = ["Ab32","ab21","aB13"]

 sorted_list = sorted(original_list)

 print(sorted_list)

結果
 ['Ab32', 'aB13', 'ab21']

大文字の方が文字コードでは値が小さいため、上のような結果になります。

これを大文字小文字を無視して並べ替えるには以下のようにします。

 sorted_list = sorted(original_list,key=str.lower)

 print(sorted_list)

結果
 ['aB13', 'ab21', 'Ab32']

str.lowerは引数を小文字にして返すメソッドです。
大文字小文字を無視するためにすべて小文字にしているわけです。
もちろん、全て大文字にするstr.upperメソッドを使っても同じ結果が得られます。

このようにkeyには何か関数やラムダ式を指定します。

指定した関数は引数として並べ替える要素が与えられ、値を返すとその結果に応じて並び替えらたリストなどがsortやsorted関数の結果となります。

例えば上のリストを4文字目で並べ替えるには以下のようにします。

 sorted_list = sorted(original_list,key=lambda x: x[3])

 print(sorted_list)

結果

 ['ab21', 'Ab32', 'aB13']

ここではラムダ式を使いましたが、「何番目の要素で並び替える」という処理はよく使うので、Pythonにはそれに対応した「itemgetter」というメソッドが用意されています。

 from operator import itemgetter

 sorted_list = sorted(original_list,key=itemgetter(3))

 print(sorted_list)

これで上のラムダ式と全く同じ結果が得られます。

こちらの方が記述が簡潔になり、かつ高速で動作します。

また、itemgetterは複数の引数を与えると、その順番に優先順位をつけてソートしてくれます。

例えば、一番目でまず並べ替え、同じ順位の間では四番目で並べ替えるには以下のようにします。

 sorted_list = sorted(original_list,key=itemgetter(0,3))

 print(sorted_list)

結果

 ['Ab32', 'ab21', 'aB13']


この例では文字列を使いましたが、リストやタプルなど、数字のインデックスでアクセスできるオブジェクトなら全く同様にソート可能です。

また、sorted関数だけではなくリストのsortメソッドにも同じ方法が使えます。

クラスオブジェクトのプロパティで並べ替えるには「attrgetter」を使います。

例えば、「name」というプロパティをもつオブジェクトのリストを並べ替えるのは以下のようなコードになります。

 from operator import attrgetter

 略

 sorted_list = sorted(original_list, key=attrgetter('name'))


  Next »[5]