問題
オブジェクトの配列から、任意のフィールド値がtrueのものだけ取り出したい
例えば、こんな配列があったとして・・・
前提条件
const items = [
{ code: 'code1', name: 'name1', checked: false },
{ code: 'code2', name: 'name2', checked: true },
{ code: 'code3', name: 'name3', checked: false },
{ code: 'code4', name: 'name4', checked: true },
{ code: 'code5', name: 'name5', checked: false }
];
checked=trueのものだけ抜き出したい場合
方法1 _.forEachでまわす
方法1
const selectedItems = [];
_.forEach(items, (item) => {
if (item.checked) {
selectedItems.push(item.code);
}
});
console.log(selectedItems);
出力結果
['code2', 'code4']
まぁ、シンプルに書くとこうなりますわって感じです
方法2 _.transformを使う
方法2
const selectedItems = _.transform(items, (result, item) => {
if (item.checked) {
result.push(item.name);
}
}, []);
console.log(selectedItems);
出力結果
['name2', 'name4']
方法1とあんまり変わらないけど、 transform
って文字列なんかカッコイイ!! とか思った人にはオススメです
方法3 _.map + _.filter を使う
方法3
const selectedItems = _.map(_.filter(items, 'checked'), 'name');
console.log(selectedItems);
出力結果
['name2', 'name4']
記事をあげたら速攻指摘いただいたので、追記しました>< ありがとうございます!
めっちゃシンプルに書けますね〜
方法3' _.map + _.filter を使う(lodashチェーン記法)
方法3'
const selectedItems = _(items).filter('checked').map('name').value();
console.log(selectedItems);
出力結果
['name2', 'name4']
方法3'' ネイティブの map + filter を使う
方法3''
const selectedItems = items.filter(obj => obj.checked).map(obj => obj.name);
console.log(selectedItems);
出力結果
['name2', 'name4']
方法3''' ネイティブの reduce を使う
方法3'''
const selectedItems = items.reduce((array, obj) => {
if (obj.checked) {
array.push(obj.name);
}
return array;
}, []);
console.log(selectedItems);
出力結果
['name2', 'name4']
ベンチマークとりました!
結果はこちら
→ https://jsperf.com/lodashbenchmark
順位 | テスト | Ops/sec |
---|---|---|
1 | reduce (ネイティブ) |
21,913 |
2 | map + filter (ネイティブ) |
20,022 |
3 | _.map + _.filter (チェーン) |
16,512 |
4 | _.transform | 13,402 |
5 | _.forEach | 11,388 |
6 | _.map + _.filter | 8,879 |
ひとこと
やっぱネイティブがlodashに比べて2倍ほど早いですね
Lodashを使うにしてもチェーン記法で書いたほうが2倍速くなるというのは発見でした
コメントしていただいたベテランJavaScripterの方々、ありがとうございました!