見出し画像

[GAS,Python] オブジェクトの配列に対してmap,filter,reduceを使用する

はじめに

GAS(JavaScript)のArrayメソッドのmap、filter、reduceメソッドと同等の処理を、Pythonで実装する場合、どう実装するのかを、備忘録としてまとめていきます。

動作環境

  • windows11

  • Jupyter Notebook 6.4.5

  • Python 3.9.7

使用するサンプルデータ

使用しているデータは、下記のサイトを使用してダミーデータを作成しました。

A列「name」、B列「price」、C列「quantity」のレコードで構成されたテーブルです。

使用するサンプルデータの構成

上記のデータを、GASでは、オブジェクトの配列として、Pythonでは、辞書型のリストとして読み込みます。

GAS:オブジェクトの配列
Python:辞書型のリスト

処理する条件

下記の条件で、処理を実装します。

  1. name列が「Lettuce」のレコード群を取得

  2. name列を取得

  3. 各レコードの合計金額から、全レコードの総合計金額を計算

name列が「Lettuce」のレコード群を取得する

GASの場合

Arrayオブジェクトのfilterメソッドを使用します。
filterメソッドは、配列から、条件を満たす要素のみを抽出することができます。条件を判定する関数で、戻り値がTrueとなる要素のみを新しい配列として返します。

const lettuceRecord = products.filter(record => record['name'] === 'Lettuce');
console.log(lettuceRecord);

実行結果は下記となりました。

filterメソッド実行結果

Googleスプレッドシートで、フィルタリングした結果と一致しています。

Googleスプレッドシートのフィルタリングした結果

Pythonの場合

方法として、2つ考えました。

1つ目は、標準関数のfilter関数を使用する方法です。
filter関数は、イテラブルなオブジェクトから、条件を満たす要素を抽出することができます。
戻り値は、filterオブジェクトになります。

lettuce_record = filter(lambda record:record['name'] == 'Lettuce', products)
print(list(lettuce_record))

filter関数の第1引数は、条件判定を行う関数を指定します。今回は、lambda式で実装しています。イテラブルなオブジェクトの各要素に対して関数を適用し、結果がTrueとなる要素のみを抜き出してきます。

第2引数は、第1引数の関数を適用したいイテラブルなオブジェクトを指定します。

また、戻り値がfilterオブジェクトとなり、そのままprint文で表示しても、中身を確認することができません。そのため、list関数でリスト型に変換します。

実行結果は下記となりました。

filter関数実行結果

2つ目の方法は、内包表記を使用する方法です。

lettuce_record = [record for record in products if record['name'] == 'Lettuce']
print(lettuce_record)

for文でリストの要素を1つずつ確認し、条件が一致する場合、そのレコードを返しています。

実行結果は下記となりました。

リスト内包表記での抽出の実行結果

name列を取得

GASの場合

Arrayオブジェクトのmapメソッドを使用します。
mapメソッドは、配列すべての要素に対して関数を実行し、実行した結果を新しい配列として返します。

const names = products.map(record => record['name']);
console.log(names);

実行結果は下記となりました。
name列のみ取得していることが確認できます。

mapメソッド実行結果

Pythonの場合

方法として、2つ考えました。
1つ目は、標準関数のmap関数を使用する方法です。
map関数は、イテラブルなオブジェクトに対して、特定の関数を適用することができます。
戻り値は、mapオブジェクトになります。

map関数の第1引数は、適用したい関数を指定します。今回は、lambda式で実装しています。イテラブルなオブジェクトの各要素に対して関数を適用します。

第2引数は、第1引数の関数を適用したいイテラブルなオブジェクトを指定します。

また、戻り値がmapオブジェクトとなり、そのままprint文で表示しても、中身を確認することができません。そのため、list関数でリスト型に変換します。

names = map(lambda record:record['name'], products)
print(list(names))

実行結果は下記となりました。

map関数実行結果

2つ目の方法は、内包表記を使用する方法です。

names = [record['name'] for record in products]
print(names)

for文でリストの要素を取得し、name列を返しています。
実行結果は下記となりました。

リスト内包表記での指定列の取得の実行結果

各レコードの合計金額から、全レコードの総合計金額を計算

GASの場合

Arrayオブジェクトのreduceメソッドを使用します。
reduceメソッドは、配列のそれぞれの要素に対して、順番に指定した関数を実行し、最後に計算結果を返すことができます。

reduceメソッドの第1引数には、前回の関数呼び出しの戻り値が格納されます。

第2引数には、現在の要素が格納されています。

また、初期値として、0を設定しています。
ここで指定する初期値は、関数が初めて呼び出された時の第1引数に格納される値となります。

const totalPrice = products.reduce((prev, cur) => prev + (cur['price'] * cur['quantity']),0);
console.log(totalPrice);

実行結果は下記となりました。

reduceメソッド実行結果

Googleスプレッドシートで計算した結果と一致しています。

Googleスプレッドシートでの計算結果

Pythonの場合

方法として、2つ考えました。
1つ目は、functoolsライブラリのreduce関数を使用する方法です。
reduce関数は、イテラブルなオブジェクトの要素に対して、指定した関数を実行し、最後に計算結果を返すことができます。

使用する際、ライブラリをインポートする必要があります。

from functools import reduce

reduce関数の第1引数は、適用したい関数を指定します。今回は、lambda式で実装しています。イテラブルなオブジェクトの各要素に対して順番に関数を適用します。

第2引数は、第1引数の関数を適用したいイテラブルなオブジェクトを指定します。

total_price = reduce(lambda prev, cur: prev + (cur['price'] * cur['quantity']), products, 0)
print(total_price)

実行結果は下記となりました。

reduce関数の実行結果

2つ目の方法は、標準関数sum関数を使用する方法です。

total_price = sum([product['price'] * product['quantity'] for product in products])
print(total_price)

sum関数の引数には、イテラブルなオブジェクトを指定します。今回は、リスト内表表記でfor文でリストの要素を取得し、price列とquantity列を掛けた値を渡しています。

実行結果は下記となりました。

sum関数の実行結果

まとめ

今回は、GASのArrayメソッドのmap、filter、reduceメソッドと同等の処理を、Pythonで実装する場合、どう実装するのかについてまとめました。
考えた方法以外にも対応方法あるかも、と思いますので、思いついたら追加していきます。

この記事が気に入ったらサポートをしてみませんか?