JavaScript を使っているなら lodash は大変便利なのですが、関数が多すぎてどれ使ったらいいのか解りづらいのが難点です。
ここではその中でも良く使う、配列ループ系の関数群を整理して紹介します。
forEach 系
- 配列/オブジェクトをループして処理する。
-
return false
でbreak
。 -
forEach: JS標準の
forEach
と違ってオブジェクトでも使える。length
プロパティがあったら配列と判断。forEachRight は逆順。 - forIn: オブジェクト専用 forEach 。length の影響受けない。親クラスのプロパティも対象。forInRight は逆順。
- forOwn: オブジェクト専用 forEach 。length の影響受けない。親クラスのプロパティは対象外。forInRight は逆順。
_.forEach([1, 2], function(value) {
console.log(value);
});
// => `1` → `2` の順に表示
_.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
console.log(key);
});
// => `a` → `b` の順に表示 (とはいえ順番は保証されない)
Map 系
- 配列/オブジェクトをループして 要素を減らさずに 値やキーを変更した新しい配列/オブジェクトを作る。
-
map: JS標準の
map
と違ってオブジェクトでも使える。 配列 を返す。
map
_.map({ 'a': 4, 'b': 8 }, n => n * n); // => [16, 64] (順序は保証されない)
// _.propertyのショートハンドが使える
var users = [{user: 'barney'}, {user: 'fred'}];
_.map(users, 'user'); // => ['barney', 'fred']
_.map(users, _.property('user')); // 同じ意味
_.map(users, u => u.user); // 同じ意味
_.mapKeys({ 'a': 1, 'b': 2 }, (value, key) => key + value); // => { 'a1': 1, 'b2': 2 }
_.mapValues({ 'a': 1, 'b': 2 }, (value, key) => key + value); // => { 'a': 'a1', 'b': 'b2' }
// id をキーにハッシュマップを作るのにも使えます。
_.mapKeys([{id: 1}, {id: 2}], v => v.id); // => { 1: {id: 1}, 2: {id: 2} }
- invokeMap: 第2引数で指定したものを関数として実行した結果で差し替える。配列 を返す。
invokeMap
_.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); // => [[1, 5, 7], [1, 2, 3]]
_.invokeMap([123, 456], String.prototype.split, ''); // => [['1', '2', '3'], ['4', '5', '6']]
reduce/transform 系
- 配列/オブジェクトをループして新しい値(accumulator)を作る。
-
reduce では
accumulator
を戻り値で返す。なのでaccumulator
に数値や boolean も使える。 -
transform では
accumulator
を関数の中で書き換える。なのでaccumulator
に使えるのは配列とオブジェクトのみ。戻り値はループを中断したい場合に使う。 - reduceRight はループが逆順に回る。
合計を作る場合
_.reduce([1, 2], (sum, n) => sum + n, 0); // => 3
各要素を二乗した新たな配列を作るが、二乗した値が奇数になったらそれ以降の値は切り捨てる場合
_.transform([2, 3, 4], function(result, n) {
result.push(n *= n);
return n % 2 == 0;
}, []);
// => [4, 9]
値とキーを逆転させる。逆転後、同一キーの値がありえるので、値は配列にする場合
// reduce で実現
_.reduce({ 'a': 1, 'b': 2, 'c': 1 }, (result, value, key) => {
(result[value] || (result[value] = [])).push(key);
return result;
}, {});
// => { '1': ['a', 'c'], '2': ['b'] }
// transform で実現
_.transform({ 'a': 1, 'b': 2, 'c': 1 }, (result, value, key) => {
(result[value] || (result[value] = [])).push(key);
}, {});
// => { '1': ['a', 'c'], '2': ['b'] }
// ちなみにこの要件なら invertBy 使ったほうが簡単
_.invertBy({ 'a': 1, 'b': 2, 'c': 1 })
// => { '1': ['a', 'c'], '2': ['b'] }