前回に引き続いてPythonのリスト内包表記について書きます。
前回の記事を書くために試したコードを載せただけの記事です。
blog.kicks.jp
後半は、辞書内包表記(Dictionary Comprehension)になっている所もあります。
- 元になるリスト(その1)
- 基本その1
- 基本その2
- 条件(Condition)を付ける
- リスト内包表記と同じ結果を得る
- 繰り返し回数を取得する
- 元になるリスト(その2)
- 条件(Condition)を付ける
- 2階層目の特定の要素だけのリストを作る
- dictのkey, valueを取得する
- dictの値を更新する
- 元のリストと同じリストを作る
- dictの特定のキーで値を書き換える
- 特定のキーだったら値を書き換える
- 要素の追加
- dict型がリストになったデータのdictに値を追加
- まとめ
元になるリスト(その1)
list1 = ['a', 'b', 'c', 'd']
基本その1
元のリストと同じリストを生成。
result0 = [v for v in list1] print(list1)
出力結果:
['a', 'b', 'c', 'd']
基本その2
要素の文字列を2文字にする。(元のリストと違ったリストにするため)
# 1. Make each element 2 chars result1 = [v + v for v in list1] print(result1)
出力結果:
['aa', 'bb', 'cc', 'dd']
条件(Condition)を付ける
'd'を除外する。
# 2. Exclude 'd' result2 = [v + v for v in list1 if v is not 'd'] print(result2)
出力結果:
['aa', 'bb', 'cc']
リスト内包表記と同じ結果を得る
forループを使った場合
# 3. Use for-loop instead of list comprehension result3 = [] for v in list1: v1 = v + v result3.append(v1) print(result3)
出力結果:
['aa', 'bb', 'cc', 'dd']
map()関数とlambda式を使った場合
# 4. Use map() and lambda in loop result1 = map(lambda val: val + val, list1) result1 = list(result1) print(result1)
出力結果:
['aa', 'bb', 'cc', 'dd']
map()関数とユーザー定義関数を使った場合
# 5. Use map() and user-defined-function def concat1(val): return val + val result5 = list(map(concat1, list1)) print(result5)
出力結果:
['aa', 'bb', 'cc', 'dd']
繰り返し回数を取得する
enumerate()で囲むと、forのあとの変数を2つ指定できて、index, valueになります。
# 6. Get index for list result5 = [v1 + str(i) for i, v1 in enumerate(list1)] print(result5)
出力結果:
['a0', 'b1', 'c2', 'd3']
元になるリスト(その2)
list2 = [ {'id': 1, 'name': 'mike'}, {'id': 2, 'name': 'susan'}, {'id': 3, 'name': 'kubotti'}, ]
前回の記事にも登場したリストです。
dict型の要素3つがリストになっています。
出力結果 :
[{'id': 1, 'name': 'mike'}, {'id': 2, 'name': 'susan'}, {'id': 3, 'name': 'kubotti'}]
条件(Condition)を付ける
# 1. Get only 1,2 result1 = [rec for rec in list2 if rec['id'] < 3] print(result1)
出力結果:
[{'id': 1, 'name': 'mike'}, {'id': 2, 'name': 'susan'}]
2階層目の特定の要素だけのリストを作る
# 2. Create list of 'name' result2 = [rec['name'] for rec in list2] print(result2)
出力結果:
['mike', 'susan', 'kubotti']
dictのkey, valueを取得する
2階層目のdictを、value(値)だけのリストにする例です。
[val for key, val in rec.items()]
とするとdictのkeyとvalueを取得できます。valueしか使っていないので、valueのリストになります。
# 3. Transform to list result3 = [[val for key, val in rec.items()] for rec in list2] print(result3)
出力結果:
[[1, 'mike'], [2, 'susan'], [3, 'kubotti']]
dictの値を更新する
# 4. Add '_1' to name result4 = [{'id': rec['id'], 'name1': rec['name'] + '_1'} for rec in list2] print(result4)
出力結果:
[{'id': 1, 'name1': 'mike_1'}, {'id': 2, 'name1': 'susan_1'}, {'id': 3, 'name1': 'kubotti_1'}]
元のリストと同じリストを作る
# 5. Do nothing result5 = [{key: val for key, val in rec.items()} for rec in list2] print(result5)
出力結果:
[{'id': 1, 'name': 'mike'}, {'id': 2, 'name': 'susan'}, {'id': 3, 'name': 'kubotti'}]
dictの特定のキーで値を書き換える
'name'の値に'_1'をつけたかったのですが最初はうまくいきませんでした。
# not work result6 = {'name':'test1' if False else 'name':'test2'}
上のコードは構文エラーになります。
以下のようにすると動いたのですが、なんでelseの後に指定できるのがvalueだけなんだろう・・?と思いました。
# 6. Add '_1' to 'name' value. result6 = [{key: value if key != "name" else value + "_1" for key, value in rec.items()} for rec in list2] print(result6)
出力結果:
[{'id': 1, 'name': 'mike_1'}, {'id': 2, 'name': 'susan_1'}, {'id': 3, 'name': 'kubotti_1'}]
調べた結果、dictを生成するときの条件は、keyとvalueそれぞれに対して書く(書ける)ということでした。
https://stackoverflow.com/questions/4260280/if-else-in-pythons-list-comprehension
# Works well result6 = {'name': 'test1' if False else 'test2'} print(result6)
# Left side 'if' statement is a conditional expression, right side 'if' is a comprehension syntax. result6 = {'name': 'test1' if False else 'test2' for k in range(1) if True} print(result6)
左側のif文は条件式(conditional expression)、右側のif文は、辞書内包表記の構文(comprehension syntax)です。
dictの条件式は、最初↓の形式かと思っていましたが、
# not work result6 = {('name1': 'test1') if False else ('name2': 'test2')}
result6 = {('name1' if True else 'name2'): ('test1' if False else 'test2')}
が正しい構文でした。
特定のキーだったら値を書き換える
result7 = [{key: value if key != 'name' else value + '_1' for key, value in rec.items()} for rec in list2] print(result7)
出力結果:
[{'id': 1, 'name': 'mike_1'}, {'id': 2, 'name': 'susan_1'}, {'id': 3, 'name': 'kubotti_1'}]
関数を使う方法:
def modify_rec(rec): record = { 'id': rec['id'], 'name': rec['name'] + '_1' } return record # 7-1. Add '_1' using map() with user-defined-function result7 = list(map(modify_rec, list2)) print(result7) # 7-2. Add '_1' using list comprehension with user-defined-function result7 = [modify_rec(rec) for rec in list2] print(result7)
出力結果:
[{'id': 1, 'name': 'mike_1'}, {'id': 2, 'name': 'susan_1'}, {'id': 3, 'name': 'kubotti_1'}]
要素の追加
リスト内包表記ではないですが、listに要素を追加。
dict1 = {'id': 4, 'name': 'taro'} list2.append(dict1) print(list2)
出力結果:
[{'id': 1, 'name': 'mike'}, {'id': 2, 'name': 'susan'}, {'id': 3, 'name': 'kubotti'}, {'id': 4, 'name': 'taro'}]
dict型がリストになったデータのdictに値を追加
[rec.update({'number': str(i+1).zfill(4)}) for i, rec in enumerate(list2)] print(list2)
出力結果:
[{'id': 1, 'name': 'mike', 'number': '0001'}, {'id': 2, 'name': 'susan', 'number': '0002'}, {'id': 3, 'name': 'kubotti', 'number': '0003'}, {'id': 4, 'name': 'taro', 'number': '0004'}]
まとめ
記事の後半はリスト内包表記と関係ない構文になってきたような・・?
役に立ちそうな例を見つけたら追記します。