【 Python 】 dict に含まれる list がすべて空か判定する方法
Python で list ( リスト ) を複数含む dict ( ディクショナリ ) の list がすべて空かどうかで処理を分けたかったので、その方法を考えてみました。
list のおさらい
とっても初歩的な内容ですが、まずは list についておさらいしてみましょう。
Python の list は大括弧 [ ] で定義します。
cat_list = ['cat1', 'cat2', 'cat3', 'cat4']
要素を参照するときは list の後ろに大括弧 [ ] を付けて要素番号で指定します。
print(cat_list[0]) # cat1
list の中身が空か判定する方法
list が空かどうか判定するには len 関数を使用します。
len 関数は list の要素数を返してくれるので、空なら 0 が返ってくるはずです。
list1 = ['cat1', 'cat2', 'cat3', 'cat4']
list2 = [ ] # 空の list
print(len(list1)) # 4
print(len(list2)) # 0
list の中身が空かどうかで処理を分けたい場合は if 文に len 関数を組み込めばよいのです。
list3 = [ ]
if len(list3):
print("list は空じゃないです")
else:
print("list は空です")
if 文では 0 以外の数値を True、0 を False と判定するので
if len(list3) == 0:
なんてしなくても大丈夫です。
dict のおさらい
Python の dict は中括弧 { } で定義します。
cat_data = {'name' : 'nyantaro', 'age' : 253, 'weight' : '8kg' }
要素を参照するときは dict の後ろに大括弧 [ ] を付けて要素名で指定します。
print(cat_data['name']) # nyantaro
dict でも len 関数は使用できます。
animal_data = {'cat' : 5, 'dog' : 3, 'opossum' : 25 }
print(len(animal_data)) # 3
len 関数の戻り値は要素数なので上記例の場合は 3 になります。
でも dict の value の合計値を出したい場合もありますよね。
dict の value の合計値を取得する方法
方法としては、dict の value だけを抜き出して sum 関数で合計するだけです。
まず、dict の value だけを抜き出すには values メソッドを使用します。
animal_data = {'cat' : 5, 'dog' : 3, 'opossum' : 25 }
print(animal_data.values()) # dict_values([5, 3, 25])
values メソッドの戻り値は list と同様に扱えるイテラブルオブジェクトなので sum 関数でそのまま合計できます。
animal_data = {'cat' : 5, 'dog' : 3, 'opossum' : 25 }
print(sum(animal_data.values())) # 33
dict に含まれる list の中身がすべて空か判定する方法
やっと本題です。
dict の value が数値ではなく list の場合に、その中身がすべて空か判定する方法を考えます。
次のような dict の場合
animal_data = {
'cat' : ['nyantaro', 'mike', 'chobi', 'belle'],
'dog' : ['pochi', 'max'],
'opossum' : ['opotaro', 'opomi', 'opojiro', 'oponosuke']
}
これらの list の中身がすべて空か判定するには、これらの list の要素数の合計を取得して if 文で 0 か 0 以外かを判定すればよいのです。
というわけで、すべての list の要素数の合計を得る方法を考えていきましょう。
まず、 dict に含まれるすべての list を values メソッドで取得してみましょう。
print(animal_data.values()) # dict_values([['nyantaro', 'mike', 'chobi', 'belle'], ['pochi', 'max'], ['opotaro', 'opomi', 'opojiro', 'oponosuke']])
分かりにくいので見やすいように直すと次のようになります。
dict_values([
['nyantaro', 'mike', 'chobi', 'belle'],
['pochi', 'max'],
['opotaro', 'opomi', 'opojiro', 'oponosuke']
])
list の中に list が格納されているような状態なのが分かるでしょうか。
これらの要素数の合計を取得するには、それぞれの list に対して len 関数で要素数を取得し、sum 関数で合計してあげればあよいのです。
方法としては 3 パターンあります。
for 文を使う方法
単純に考えれば for 文で各リストの要素数を足し合わせていけば合計を得られますね。
num = 0
for value in animal_data.values():
num += len(value)
if num:
# 空でない場合 ( num > 0 ) の処理
else:
# 空の場合 ( num = 0 ) の処理
これくらいの内容ならば for 文で十分事足ります。
だけど、Python には for 文で記述するよりももっとスマートな方法があります。
map 関数を使う方法
マップ関数とは、list などのイテラブルオブジェクトの各要素に対して指定した関数を実行した結果を格納したイテラブルオブジェクト ( map object ) を返す関数です。
https://docs.python.org/ja/3/library/functions.html#map
言葉で説明するのがちょっと難しいですが、次のように使います。
if sum(map(len, animal_data.values())):
# 空でない場合の処理
else:
# 空の場合の処理
map(len, animal_data.values()) とした部分で animal_data.values() の各要素に対して len 関数を実行して map object に格納されます。
list で表すと [4, 2, 4] という感じで各 list の要素数を列挙した形になります。
それをさらに sum 関数で合計しています。
内法表記を使う方法
内包表記とは、list などのイテラブルオブジェクトから別のイテラブルオブジェクトを作成できる書き方です。
これも言葉で説明するのは難しいのですが、次のように使います。
if sum([len(value) for value in animal_data.values()]):
# 空でない場合の処理
else:
# 空の場合の処理
[len(value) for value in animal_data.values()] とした部分が list 内包表記という書き方で、[4, 2, 4] といった感じの list になります。
それをさらに sum 関数で合計しています。
まとめ
dict に含まれる list がすべて空か判定する方法は dict.values() ですべての list を取得して len 関数でそれぞれの要素数を取得して sum 関数で合計し、0 かどうか判定すればよいということが分かったでしょうか。
map 関数や内包表記は初心者の方には少し難しいかもしれませんが、for 文よりも少ないコードで書ける上に処理速度も速くなるという利点があります。
このあたりがうまく使いこなせるようになると Python のレベルが一つ上がったような実感が得られるはずです。