#JavaScript の配列には #コールバック を抱えて走ってくれるメソッドがあります。
コールバックを利用すること自体はほかのメソッドでも自作メソッドでもできるのですが、これらのメソッドはビルトインオブジェクトの中で全ての要素を参照していく仕様になっています。よって、記述が端的になるばかりでなく処理速度も速いと予想されます。これらの積極的利用はアプリケーションの作動速度に好ましい影響があるのではないかと期待しています。
前回の投稿では #map と #filter を紹介しました。今回は #some と #every です。
前回投稿の最後で、私がsomeとeveryを使ったことがない旨を述べました。これまでのメソッドは条件に合わせて処理をしてくれたのですが、この二つメソッドは配列内の条件テストをして真偽の結果を返すだけなので、利用の場面に当たっておりません。でも、正規表現オブジェクトのtestメソッド同様に高速処理が期待できますので、有効利用できる場面が来たらサラッと記述できるようにしておきたいものです。
まずは以前の投稿と同じく検証用の #多次元配列 ( #MIME と #拡張子 セットのテーブル)を生成します。つづくターミナル表示は、macOS上でSafariでのコンソール出力の表記です。また、「>」がコンソールへ私が打ち込んだ入力テキストで、「<」がリターンキーを押すと現れる出力情報です。
> tbl = new Array( ['text/plain','txt'], ['text/csv','csv'], ['text/tsv','tsv'], ['text/css','css'], ['text/javascript','js'], ['text/xml','xml'], ['text/html','html']); < [["text/plain", "txt"], ["text/csv", "csv"], ["text/tsv", "tsv"], ["text/css", "css"], ["text/javascript", "js"], ["text/xml", "xml"], ["text/html", "html"]] (7)
以前からの投稿同様に、よくある解説では、some(callback [, that])とあって、「thatパラメータは関数callback内でthisを示すオブジェクト」だそうです。ここではアロー関数ばっかり使うのでthatの出番はありません。callbackの中身はsome(function(要素, 位置, 配列) {})と表記されます。「要素」は繰り返し処理される配列の一要素、「位置」はその要素の配列内のインデックス、「配列」は処理される配列そのものです。everyも同じです。いままでの #forEach や #map 、 #filter と全く同じです。それではアロー関数の先で、子配列の各要素に条件を当ててみましょう。比較的に簡単なのでどんどん行っちゃいます。
> tbl.some((vc, id, ar)=>(vc[1]==='css')) < true > tbl.every((vc, id, ar)=>(vc[1]==='css')) < false
someとeveryの双方で、テーブル要素の拡張子の方(idが1の末尾要素)の文字列が’css’であるかの条件をtbl配列の全要素に問うています。
someは配列内でどれか一つでも条件に適合すれば真を返します。この場合は’css’が一つありますから、真のtrueになります。
everyは配列内の全てが条件に適合すれば真を返します。この場合は’css’が一つだけで他は違いますから、偽のfalseになります。
> tbl.some((vc, id, ar)=>(vc[0].indexOf('css')!==-1)) < true > tbl.every((vc, id, ar)=>(vc[0].indexOf('css')!==-1)) < false
テーブル要素のMIMEの方(idが0の先頭要素)の文字列に’css’が含まれるかの条件を問うても結果は同じです。
では、テーブル要素のMIMEの方の文字列に’text’が含まれるかの条件を問うてみましょう。
> tbl.some((vc, id, ar)=>(vc[0].indexOf('text')!==-1)) < true > tbl.every((vc, id, ar)=>(vc[0].indexOf('text')!==-1)) < true
全部に’text’が含まれていますからsomeもeveryも真(true)になりましたね。
この利用方法だとsomeはともかく、everyは利用価値を感じませんよね?
でも、たとえば配列要素のMIMEの方がすべてテキスト(string)であるかの条件を問うてみます。
> tbl.every((vc, id, ar)=>(typeof(vc[1])==='string')) < true
真(true)が返ってきました。となれば、全部がテキストだから安心して処理が進められると、なります。実際はもう少し踏み込んだ条件になるとは思いますが、有効利用する考え方は間違っていないと思います。
でも条件が複雑になると、偽(false)であった場合の対応が優先されてforEachとかmapの出番になり、everyの出番がなくなってしまいます。
あまり想像したくありませんが、利用が有効と考えられるのは大量データの検索を行うときぐらいではないかと予想しています。はたして私がsomeやeveryと打ち込む日は来るのでしょうや。
> tbl < [["text/plain", "txt"], ["text/csv", "csv"], ["text/tsv", "tsv"], ["text/css", "css"], ["text/javascript", "js"], ["text/xml", "xml"], ["text/html", "html"]] (7)
もとのテーブルを参照して、これらメソッドが #非破壊 であることを確認しておきます。
someとeveryの紹介は、使ったことがない故にこの程度であまり深くありません。(すみません。)次は #reduse #reduseRight を紹介する予定です。これらは要件が増えるので複雑で厄介です。でもとても便利ですよ。と自分に言い聞かせて検証にあたります。そかさ。