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

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

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

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

Q&A

解決済

1回答

800閲覧

dictionaryのfor文について

khayato0512

総合スコア24

Python 3.x

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

0グッド

0クリップ

投稿2019/04/06 01:04

前提・実現したいこと

codecademyでdictionaryの課題をやっています。
その内容は、namesと言うdictionaryのなかにラストネームがkeyとして入っていて、ファーストネームがvalueとして入っています。そして同じラストネームの頭文字を持つ人を数えて、それをその頭文字をkey、人数をvalueとして新しいdictionaryのlettersにまとめようとしています。

発生している問題・エラーメッセージ

エラーは出ませんが、出るはずの答えと一致しません。
例えば下のコードだと、本当は{‘S’: 4, ‘L’: 3}.と出したいのですが、
{‘S’: 3, ‘L’: 3},や{‘S’: 1, ‘L’: 3}と出てしまいます。
なぜ予想される答えが出ないのか、また、同じコードなのになぜ答えがふた通り出てしまうのか分かりません。

エラーメッセージ

該当のソースコード

python3

1# Write your count_first_letter function here: 2def count_first_letter(names): 3 letters={} 4 for key,value in names.items(): 5 if key[0] in letters: 6 letters[key[0]]+=len(value) 7 8 9 letters[key[0]]=len(value) 10 11 12 return letters 13 14 15 16# Uncomment these function calls to test your function: 17print(count_first_letter({"Stark": ["Ned", "Robb", "Sansa"], "Snow" : ["Jon"], "Lannister": ["Jaime", "Cersei", "Tywin"]}))

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

なぜ予想される答えが出ないのか

if文において条件が成立しない場合の処理を記述するためにはelse節として記述しないといけません。

python

1 if key[0] in letters: 2 letters[key[0]] += len(value) # (A) 3 letters[key[0]] = len(value) # (B)

こう書くと条件が成立して(A)が実行された後(B)も無条件に実行されるため(A)を行うことに意味がなくなってしまいます。それが期待どおりの動作にならない原因です。

質問者さんの意図するように動作するためには例えばこう書くべきです。

python

1 if key[0] in letters: 2 letters[key[0]] += len(value) 3 else: 4 letters[key[0]] = len(value)

同じコードなのになぜ答えがふた通り出てしまうのか分かりません。

質問者さんのコードだと「ある頭文字に対する値がファミリーネームの合計ではなくnamesから列挙した「最後のファミリーネームの数」によって決まってしまうので列挙される順序によって結果が異なってしまいます。Python 3.6以降のdictは列挙した順序が実行の度に変わることはありませんが、Python 3.5以前のdictは列挙した際の順序が「不定」でした。おそらくcodecademyのPythonインタープリタのバージョンは3.5より古いのだろうと思います。

https://docs.python.org/ja/3.7/library/stdtypes.html#dict

バージョン 3.7 で変更: 辞書の順序が挿入順序であることが保証されるようになりました。この振る舞いは CPython 3.6 の実装詳細でした。


なお、本件に関して言えばdictよりcollections.defaultdictを用いたほうがシンプルに実装できます。

python

1from collections import defaultdict 2 3def count_first_letter(names): 4 letters = defaultdict(int) 5 for key, value in names.items(): 6 letters[key[0]] += len(value) 7 return letters

defaultdictを用いるとキーが登録済みかどうか気にする必要は最早ありません。登録されていないキーに対する値が自動的に特定の値(上の例では0、詳しく言えばint()の結果)と仮定されるからです。

https://docs.python.org/ja/3.7/library/collections.html#defaultdict-objects

投稿2019/04/06 04:04

KSwordOfHaste

総合スコア18392

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

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

khayato0512

2019/04/06 15:34

とても詳しく説明してくださり、大変助かりました。if文で出した結果を台無しにしている構造に気づきました。 また、追加でのdefaultdictのアドバイス、ありがとうございます。学習して自分のモノにできるようにします。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問