Quantcast
Channel: 配列タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 757

ワイ「なに!?型のズレを吸収できるやと!?」

$
0
0

前回の記事、
4歳娘「パパ、20歳以上のユーザーを抽出して?」
の続きやで!

休日ワイ

ワイ「最近、コロナウィルスの影響でリモートワークがメインになってしもうたから」
ワイ「家でも快適にお仕事ができるように、42.5インチの特大モニタを買ったで!」
ワイ「やっぱデッカいモニタはええな〜」
ワイ「インデントも思いっ切り入れれるわ」

スクリーンショット 2020-04-04 13.42.28.png

よめ太郎「さすがに入れすぎやろ・・・」

ワイ「私のインデントは53ですいうてな」

よめ太郎「いやフリーザ様どこで勝負してんねん」
よめ太郎「しかもインデント奇数なんかい」

娘(4歳)「ねえ、パパ?」

ワイ「ん?」
ワイ「なんや、娘ちゃん」

娘「その大きいモニタを使って、早速やってほしい作業があるの」

ワイ「おお、ええでええで!」

娘ちゃんの依頼内容

娘「実は、こないだ山で拾ってきた家族風オブジェクトに、子供が増えてて」
娘「オブジェクトの内容が変わっちゃったの」

JavaScript
constfamily={mother:{name:"よめ太郎",age:35},father:{name:"やめ太郎",age:37},children:[{name:"娘ちゃん",age:4},{name:"ボブ",age:39}]};

娘「daughterchildrenになっちゃったの」

ワイ「ん?どういうことや?」

娘「前回は娘が1人だけだったからdaughterっていうオブジェクトだったけど」
娘「子供が1人増えて、childrenという配列になっちゃったの」
娘「だから、20歳以上のユーザーを上手く抽出できなくなっちゃったの」

ワイ「そ、そうなんか」
ワイ「でも、子供たちはどうせ20歳未満なんやから」
ワイ「motherfatherだけ取り出せばええんちゃうの?」

娘「それが・・・弟のボブは養子で39歳なの」

ワイ「Oh...ボブ...」
ワイ「ワイの知らん間に子供が増えてるから、少しおかしいなって思ったけど」
ワイ「そういう事情やったんか」
ワイ「これは、ワイだけでは無理や」
ワイ「ハスケル子ちゃんを呼ぼう」

ハスケル子もTV会議で参戦

ワイ「もしもし、ハスケル子ちゃん?」

ハスケル子「はい」
ハスケル子「私を呼ぶってことは、ボブの件ですね」

ワイ「さすがハスケル子ちゃん、話が早いわ」

よめ太郎「(いや早すぎやろ)」

オブジェクトと配列が混ざっている件

ワイ「motherfatherはオブジェクトなのに」
ワイ「childrenは配列やねん」
ワイ「オブジェクトと配列が混ざってんねん」

娘「そうなの」
娘「そこから、20歳以上のユーザーを抽出して」
娘「以下のようなotonaArrayっていう配列を作りたいの」

JavaScript
[{name:"よめ太郎",age:35},{name:"やめ太郎",age:37},{name:"ボブ",age:39}]

ハスケル子「うーん」
ハスケル子「オブジェクトと配列が混じってて扱いづらいなんて・・・」
ハスケル子「そもそも仕様とか設計の問題のような・・・」
ハスケル子「もっと、サーバサイドでデータを整形してから返したほうが・・・」

ワイ「いや、仕様とか設計とかサーバサイドとかじゃないねん」
ワイ「山で拾ったオブジェクトなんやから」
ワイ「もうボブは家族なんやから」

ハスケル子「やむを得ないですね」
ハスケル子「分かりました」
ハスケル子「大人だけを抽出したotonaArrayという配列を作ればいいんですね」

まずはObject.entries()map()

ハスケル子「familyというオブジェクトを元に配列を作るので」
ハスケル子「まずはObject.entries(family)ですね」
ハスケル子「そのあと配列のmap()メソッドでmotherfotherchildrenの中身を取り出します」

JavaScript
constfamilyArray=Object.entries(family).map(([,personOrArray])=>personOrArray);

ハスケル子「こうですね」

ワイ「おお、オブジェクトのkey名は使わずに中身だけ取り出す感じやね」
ワイ「personOrArrayには、motherfatherchildrenの中身が入ってんねやな」

ハスケル子「はい」
ハスケル子「こうすることで、familyArrayの中身は・・・」

JavaScript
// familyArrayの中身[{name:"よめ太郎",age:35},{name:"やめ太郎",age:37},[{name:"娘ちゃん",age:4},{name:"ボブ",age:39}]]

ハスケル子「↑こんな風になります」

ワイ「おお、あとはこの中から20歳以上のユーザーを抽出すんねやな」
ワイ「でも、オブジェクトと配列が混じってるけど大丈夫なん?」

ハスケル子「余裕です」
ハスケル子「配列のflat()メソッドを使って」
ハスケル子「ネストした配列から1段階フラットな配列を作ります」

JavaScript
constflatFamilyArray=familyArray.flat()

ハスケル子「↑こうですね」
ハスケル子「すると・・・」

JavaScript
// flatFamilyArrayの中身[{name:"よめ太郎",age:35},{name:"やめ太郎",age:37},{name:"娘ちゃん",age:4},{name:"ボブ",age:39}]

ハスケル子「↑こんな感じのflatFamilyArrayが出来上がります」

ワイ「おお」
ワイ「子供の配列が1段階フラットになって、単なるフラットな配列になってフラットやな!」

よめ太郎「(語彙どうなってんねん)」

ワイ「あとはfilter()20歳以上のユーザーを抽出するだけやな・・・!」

ハスケル子「はい」
ハスケル子「なので、いちいち変数に入れずにまとめて書くと・・・」

JavaScript
constotonaArray=Object.entries(family).map(([,personOrArray])=>personOrArray).flat().filter(person=>person.age>=20);

ハスケル子「↑こうですね」
ハスケル子「すると・・・」

JavaScript
// otonaArrayの中身[{name:"よめ太郎",age:35},{name:"やめ太郎",age:37},{name:"ボブ",age:39}]

ハスケル子「↑こんな感じの、大人だけを集めたotonaArrayが出来あがります」

ワイ「まじか〜」
ワイ「flat()メソッド便利やな」

ハスケル子「はい」

ワイ「今までのワイやったらflat()メソッドなんて知らんかったから」
ワイ「Array.isArray()メソッドを使って」
ワイ「配列ならこう、配列じゃなければこう・・・みたいな感じで」
ワイ「if文とかで条件分岐しながら」
ワイ「配列の詰め直しをしとったところやわ」

ハスケル子「なるほど」
ハスケル子「つまり・・・」

JavaScript
// まず空配列を生成。constflatFamilyArray=[];familyArray.forEach(personOrArray=>{// if文で配列かどうか判断しながら詰め直していく。if(Array.isArray(personOrArray)){// 配列の場合はスプレッドで展開してpush。flatFamilyArray.push(...personOrArray);}else{// 配列じゃない場合はそのままpush。flatFamilyArray.push(personOrArray);}});

ハスケル子「↑こういう感じで処理するってことですよね」

ワイ「せやせや」

ハスケル子「空配列を作って、そこにどんどん詰め直していく・・・」
ハスケル子「そういった、副作用と手続きの連続で書くのもまあ」
ハスケル子「分かりやすいといえば分かりやすいので良いんですけど」
ハスケル子「私はやっぱり」

JavaScript
constotonaArray=Object.entries(family).map(([,personOrArray])=>personOrArray).flat().filter(person=>person.age>=20);

ハスケル子「↑この、メソッドの連続で書ける関数型な感じが好きですね」

ワイ「なるほどなぁ・・・」
ワイ「flat()はなんか、if文を内包してるようで」
ワイ「魔法みたいやな」

ハスケル子「ちょっとそんな感じですよね」
ハスケル子「たとえば・・・」

JavaScript
[3].flat()// -> [3][[3]].flat()// -> [3]

ハスケル子「↑こんな感じで」
ハスケル子「元の値が3であろうと[3]であろうと」
ハスケル子「一度[]で包んでflat()してやれば」
ハスケル子「同じ[3]になる・・・」
ハスケル子「こういう型ハックみたいなの楽しいですよね」

ワイ「なるほどな」
ワイ「[3]flat()しても、ただの3にはならないんやな」
ワイ「せやから[3].flat()してやることで型を合わせられる・・・」

ハスケル子「はい」
ハスケル子「ちなみに」
ハスケル子「map()した後にflat()してる部分は」
ハスケル子「flatMap()メソッド1つでも行けます」

ワイ「ま、まじか・・・」
ワイ「そんな都合の良いメソッドが・・・」

ハスケル子「はい」
ハスケル子「さっきのfamilyオブジェクトの例で言うと・・・」

JavaScript
constotonaArray=Object.entries(family).flatMap(([,personOrArray])=>personOrArray).filter(person=>person.age>=20);

ハスケル子「↑こんな感じです」

ワイ「なるほどなぁ・・・」
ワイ「オブジェクトから配列に変換しつつ、フラットにして、フィルタリングする・・・」
ワイ「なんかカッコええね」

ハスケル子「そうなんです」

まとめ

  • flat()はネストした配列を1段階フラットにしてくれる。
    (引数を与えることで2段階、3段階フラットにすることも可能)
  • map()した後にflat()するなら、flatMap()でもOK。

ワイ「↑こんな感じやね!」

ハスケル子「はい」
ハスケル子「今回みたく、オブジェクトと配列を同列に扱わないといけない、なんてのは」
ハスケル子「そもそも設計が微妙な感じもしますけど」
ハスケル子「例えば、スクレイピングで取得したデータとかの場合は」
ハスケル子「データの形式を自分で決められないので」
ハスケル子「こういうハックが役に立つこともあるかもしれませんね」
ハスケル子「もし思い出したら、使ってみてください」
ハスケル子「たまに便利ですよ!」

ワイ「なるほどな」

ハスケル子「でも、ズレてる型を何とかするために」
ハスケル子「仕方なくflatMap()を使うより」
ハスケル子「もっと能動的に使った方が楽しいです」

ワイ「能動的に?」
ワイ「どういうこと・・・?」

ハスケル子「もうちょっと本来のflatMap()使い方って感じです」
ハスケル子「それはまた次回お話しますね」

ワイ「おお、なんか楽しみやな・・・!」

〜つづく〜

参考文献

注意

もちろんIEでは使えへんで!!!


Viewing all articles
Browse latest Browse all 757

Trending Articles