map の例
var a=[1,2,3,4,5]
a.map(e=>e*3) // 各要素を3倍する
[...Array(30).keys()].map(e=>2**e) // 2のべき乗の数が並ぶ配列
[...Array(30).keys()].map((e,i)=>[2**e,i]) // 乗数を添えたタプル列
filter
[...Array(30).keys()].filter(e=>e%3==0) // 3の倍数だけを選ぶ
%
(剰余)や==
(比較)といった演算子の用法はRubyとほぼ同じ。reduce
[...Array(30+1).keys()].reduce((r,e)=>r+e) // 階和(1から30まで)
[...Array(30+1).keys()].slice(1).reduce((r,e)=>r*e) // 階乗(同)
// 階乗の場合はsliceで0を取り除いておかないと意味のない数値になる
// 大きな数になるとJSでは通常のNumber型で扱えず、
// Float型で近似することになる。整数で計算するには、
[...Array(30+1).keys()].slice(1).map(e=>BigInt(e)).reduce((r,e)=>r*e)
// のようにBigInt型に変換してから掛け合わせる
// (末尾に 'n' が付加されている表現が BigInt)
[...Array(30).keys()].reduce((r,e)=>r+e,"")
// 初期値として空文字列を渡すと、同じ `+` 演算子を使っていても、
// 文字列の連結として処理される
every, some: いずれも高階関数として動作し、全体の値として論理値を返す。
Rubyの、Array#all?
、Array#any?
にブロックを渡した場合と意味的には同じだが、
結果がわかった(everyではfalseになる要素があった時点、someではtrueになった時点)でそれ以降の検査(呼出)はしない(この点は Rubyの動作とは違うようだ)。
RubyのArrayクラス(+ Enumerableモジュール)に比べると、 JSの配列に(ネイティブで)提供されている機能(メソッド)の数は少ない。
が、それを補うように、第3者が提供する機能(ライブラリ)が充実しているので、 必要に応じてライブラリの活用を考えるといい。代表的なものとして underscore.js や Lodash がある。
1から100までの数を4乗した数の列の中で、 (どこかの桁に)6という文字を含むものだけを選び出す(順々に作っていこう)。
まずは出発点になる配列
[...Array(100).keys()]
// => [0,1,2,3,...99] // 1から100にしたいので...
[...Array(100).keys()].map(n=>n+1)
// または...
[...Array(100+1).keys()].slice(1)
// => [1,2,3,...100] // これを(それぞれ)4乗する
[...Array(100).keys()].map(n=>(n+1)**4)
// map を連結して使ってもいいが、1つのmapで +1 と4乗をまとめてすます
文字列への変換と、6を含むかどうかの検査
1.toString() // => ERROR ピリオドが小数点と解釈されようとするようだ
// ので、以下のように回避すればいい
var n=1
n.toString()
// または
(1).toString()
String(1) // こういう変換方法もある
// 今のは少し寄り道になった。変数に対してのメソッド呼出なら普通に書けばいい
'12345678'.indexOf('6') // => 5
'12345678'.indexOf('9') // => -1
// この値が0より大きいかどうかで判断できそう
'12345678'.match(/6/) // => ['6', index:5, ...]
'12345678'.match(/9/) // => null
// この式はそのまま論理式として使える
フィルター:
ここでは行長の都合で適当な場所で改行を入れて複数行に渡る1つの式を提示している (メソッド呼出のピリオドの直後での改行はよく使われる)。
[...Array(100).keys()].map(n=>(n+1)**4).
filter(n=>String(n).indexOf('6')>=0)
// または
[...Array(100).keys()].map(n=>(n+1)**4).
filter(n=>String(n).match(/6/))
もとの数と4乗した結果を示すような表記にする。
[...Array(100+1).keys()].slice(1).
filter(n=>String(n**4).indexOf('6')>=0).
map(n=>`${n}**4 => ${n**4}`)
(第9回資料末尾に掲示したプログラムに相当するもの)
1~100からなる配列
var a=[...Array(101).keys()].slice(1)
(1.の配列について)各要素を3倍する
a.map(n=>n*3)
(1.の配列について)3の倍数だけを選び出す
a.filter(n=>n%3==0)
a’ ~ ’z’までの文字列からなるサイズ26の配列:
[...Array("z".charCodeAt()+1).keys()].
slice("a".charCodeAt()).
map(e=>String.fromCharCode(e))
[1, 2, 3, 1, 2, 3, …] と繰り返す サイズ20の配列
Array(20).fill().map((_,i)=>i%3+1)
乱数からなる配列を作る
Array(20).fill().map(()=>Math.random())
最大のものを見つける
a.reduce((r,v)=>r>v?r:v)
Math.max(...a)
で求められる(がここでは練習のため reduceを使った)。発展:最大のものが何番目だったか:
a.map((e,i)=>[e,i]).
reduce(([mx_v,mx_p],[e,i])=>mx_v>e?[mx_v,mx_p]:[e,i])