質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

8392閲覧

dict.sort(key=lambda)を使ったとあるコードの仕組みに関して

suuuu

総合スコア15

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2018/11/11 02:49

質問したいこと

dict.sort(key=lambda)を使ったとあるコードの仕組みに関して

質問の詳細

私は、Pythonを学習しており、とあるコードの仕組みが理解できず困っております。
コードの内容は以下です。

>>> dict = [(1,'Nomura'),(2,'Nagashima'),(3,'Miyamoto'),(4,'Hoshino')] >>> dict.sort(key=lambda dict: dict[1]) >>> dict [(4, 'Hoshino'), (3, 'Miyamoto'), (2, 'Nagashima'), (1, 'Nomura')]

最終的に「>>> dict」の出力結果が上記のようになる仕組みが理解できません。
これは恐らく、Value値の昇順になっていると予測していますが合っているでしょうか。
予測の根拠は、以下のコードに書き換えて実行してみると、Value値の昇順になっているように思えたからです。

>>> dict =[(1,'Hoshino'),(2,'Miyamoto'),(3,'Nagashima'),(4,'Nomura')] >>> dict.sort(key=lambda dict: dict[1]) >>> dict [(1, 'Hoshino'), (2, 'Miyamoto'), (3, 'Nagashima'), (4, 'Nomura')]

私のlambdaに対する認識は、関数のように動き、「dict: dict[1]」の左辺dictが返り値、dict[1」が関数式であるということぐらいです。
dict.sort()に関しては、引数を渡さない場合は Index値の昇順に並び変えるという認識です。
(上記は自分で調べた結果、自分なりに理解したもので、間違い等あればご指摘お願いします)

sortに Value値を渡すとValue値の昇順で並び変えるのでしょうか。
仕組みをご教示いただけると嬉しいです。
よろしくお願い致します。

補足情報(FW/ツールのバージョンなど)

Python 3.6.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

私のlambdaに対する認識は、関数のように動き、「dict: dict[1]」の左辺dictが返り値、dict[1」が関数式であるということぐらいです。

この場合dictが引数、dict[1]が返り値です。
次のように関数をキーを与えるのと、意味は同じです。

Python

1def get_key(arg): 2 return arg[1] 3 4dict.sort(key=get_key)

これは恐らく、Value値の昇順になっていると予測していますが合っているでしょうか。

試しにキー関数の中にprintを仕込んでみます。

Python

1>>> def get_key(arg): 2... print(type(arg), arg) 3... return arg[1] 4... 5>>> dct =[(1,'Hoshino'),(2,'Miyamoto'),(3,'Nagashima'),(4,'Nomura')] 6>>> dct.sort(key=get_key) 7<class 'tuple'> (1, 'Hoshino') 8<class 'tuple'> (2, 'Miyamoto') 9<class 'tuple'> (3, 'Nagashima') 10<class 'tuple'> (4, 'Nomura')

このように、各組が順に渡されていることが分かります。
このとき、get_keyは各組の名前の部分を返すので、結局文字列の比較に落とし込まれます。

文字列の比較については、ここに解説があります。
Python チュートリアル » 5.8. シーケンスとその他の型の比較

シーケンスオブジェクトは同じシーケンス型の他のオブジェクトと比較できます。比較には 辞書的な (lexicographical) 順序が用いられます。

ただし、ここでの『辞書的順序』は文字コード順を指すことに注意は必要です。

Python

1>>> sorted(['abc', 'def', 'DEF']) 2['DEF', 'abc', 'def']

投稿2018/11/11 03:08

編集2018/11/11 03:12
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suuuu

2018/11/11 05:27

>この場合dictが引数、dict[1]が返り値です。 理解しました。文法をまだ押さえることができていなかったようです。 >get_keyは各組の名前の部分を返すので、結局文字列の比較に落とし込まれます。 これがソート結果の仕組みですね。 文字コード順というのも、とても有益な情報です。 ありがとうございます。
guest

0

まず最初に理解されてほしいのは、例示されているdictは辞書ではなくリストであるということです。そしてリストの各要素は(1,'Nomura')のようなタプルです。

これは恐らく、Value値の昇順になっていると予測していますが合っているでしょうか。

~~違います。~~合ってます。この例でいえばNomuraなどの名前の昇順になっています。

私のlambdaに対する認識は、関数のように動き、「dict: dict[1]」の左辺dictが返り値、dict[1」が関数式であるということぐらいです。

dict.sort()に関しては、引数を渡さない場合は Index値の昇順に並び変えるという認識です。
(上記は自分で調べた結果、自分なりに理解したもので、間違い等あればご指摘お願いします)

違います。lambda item:item[1]において、ソート時にリストの各要素が引数としてitemに入ってこの関数が呼び出されます。今の例では各要素のタプルがitemに入ってきます。

次に「:」の右側はlambda関数の戻り値となります。この戻り値は、その要素の並び順を他要素と比較し決定するための値です。
例えばitem[1]であればタプルの1番目の要素のNomuraなどの名前を返すことになります。
sort関数は、これら各要素の戻り値NomuraNagashimaを用いて要素を並べ替えます。

参考:pythonのsorted関数で使われるlambdaとは何なのか

Python

1# リストの確認 2lst = [(1,'Dave'),(2,'Charlie'),(3,'Bob'),(4,'Alice')] 3item= lst[2] # 2番目の要素(=タプル) 4print(item) # タプル「(3,'Bob')」 5print(item[0])# 数値「3」 6print(item[1])# 名前「Bob」 7 8# [0]=数値の昇順 9lst.sort(key=lambda item: item[0]) 10print(lst) # [(1, 'Dave'), (2, 'Charlie'), (3, 'Bob'), (4, 'Alice')] 11 12# [1]=名前の昇順 13lst.sort(key=lambda item: item[1]) 14print(lst) # [(4, 'Alice'), (3, 'Bob'), (2, 'Charlie'), (1, 'Dave')]

投稿2018/11/11 03:17

編集2018/11/11 03:24
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2018/11/11 03:22

>次に「:」の左側は 右です
can110

2018/11/11 03:23

あ!ご指摘ありがとうございます。 ボケてました。
suuuu

2018/11/11 05:32

>lambda item:item[1]において、ソート時にリストの各要素が引数としてitemに入ってこの関数が呼び出されます。今の例では各要素のタプルがitemに入ってきます。 他の方の回答も読んで、理解しました。 lambda関数を引数として、dict[1]=タプルの右側の値(文字列型)によってソートされているということですね。 最後に挙げていただいている参考コードの仕組みも意味が分かったのでとりあえず納得できました。 ありがとうございます。
guest

0

ベストアンサー

lambdaに関する認識がそもそも間違っていると思います。lambda式が返すのは関数そのものです。フォーマットはlambda 仮引数 : 式というものです(厳密ではありません)。

なので、質問文の関数は次のように働きます。

python

1>>> (lambda x : x[1])(("hoge", "fuga")) # 直接callしている。引数の名前は仮引数なので何でも良い 2'fuga' 3>>> f = lambda x : x[1] # 混乱しそうなので直接callしないパターンも示します 4>>> f(("hoge", "fuga")) 5'fuga'

次にソートについてですが、そのオブジェクトの型はlistなので、ドキュメントのlist.sortメソッドの節を参考にしてください。

key は一引数をとる関数を指定し、リストのそれぞれの要素から比較キーを取り出すのに使います (例えば、 key=str.lower)。それぞれの項目に対応するキーは一度計算され、ソート処理全体に使われます。デフォルトの値 None は、別のキー値を計算せず、リストの値が直接ソートされることを意味します。
4. 組み込み型 — Python 3.6.5 ドキュメント #list.sort

つまり、各要素に対してkeyの関数を適用した結果に対してソートが行われる、ということが書いてあります。

python

1>>> (lambda x : x[1])((1,'Hoshino')) 2'Hoshino' 3>>> (lambda x : x[1])((2,'Miyamoto')) 4'Miyamoto'

確かに質問文のコードでは結果的にvalue(と便宜的に呼ぶことにするが、そもそもdict型ではないのでキーと値の概念はない)でソートされますが、常にそうなるわけではありません。たとえばkey=lambda x : x[0]とすればlistの要素の各タプルの最初の要素(1,2,3,4)に対してソートされることでしょう。

ところで

dictという変数名は組み込みのdictクラスを上書きしてしまうので、使うべきではありません。

あと、dictといいつつ実体がlist型なのも混乱する。書籍、サイト、教材等でそのコードが出てきたのなら、そこの情報は信頼できない可能性があります。

補足

引数を渡さない場合は Index値の昇順に並び変える

について。

list.sortメソッドのkeyが指定されない場合、上で引用した通りリストの要素がそのまま比較されます。

タプル同士は比較できます。

python

1>>> (1,2,8) > (2,5,6) 2False 3>>> (1,0,0) > (1,0) 4True 5>>> (1,'Hoshino') < (2,'Miyamoto') 6True

5. データ構造 — Python 3.6.5 ドキュメント # シーケンスとその他の型の比較

詳細は割愛しますが、左側の要素から一桁ずつ比較されます。なので質問文のコードであれば、index(と便宜的に呼びますが以下略)で比較されているように見える、という訳です。

投稿2018/11/11 03:07

編集2018/11/11 03:26
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suuuu

2018/11/11 05:22

ご親切に回答いただきありがとうございます。 >フォーマットはlambda 仮引数 : 式 私が戻り値と思っていたのは仮引数なのですね。 key値にlambda式を渡し、関数の処理結果がソートに影響しているという解釈で合っていますか。 x[1]でタプルの右値が評価されている理屈は分かりました。 元々の問題はdictではなくdicと書いてあったのですが、私は全体がリスト型であるということもよく認識できていなかったようです。 もっと勉強が必要ですね。
hayataka2049

2018/11/11 05:36

>key値にlambda式を渡し、関数の処理結果がソートに影響しているという解釈で合っていますか。 関数で処理した結果に基づいてソートされるということですね
suuuu

2018/11/11 05:37

理解しました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問