リスティング広告代行の専門会社|Yahoo!プロモーション広告・Google AdWords完全対応|東京・大阪・名古屋

underscore.jsを使ってみました


image

underscore.jsとは?

配列・オブジェクトの操作(検索、演算、列挙など)をよりシンプルに記述するためのライブラリです。
HTMLのscriptタグで読み込みするだけですぐに使うことができます。

まず読み込んでみよう

2014/02現在の最新版は1.6.0です。

  • 公式サイトを開きます。
  • ダウンロードする人は「Donwloads」を、bowerなどでインストールする人は「Installation」を参照してください。
  • HTMLにscriptタグを書きます。underscore.jsまたはunderscore-min.jsを読み込みします。
  • 準備OK。

何が便利?

例えばこんな配列があったとします。

member = [
    {id:1, name:'yamada', age:15, gender:'male', score:30, num:[11,12,21,10]},
    {id:2, name:'suzuki', age:46, gender:'female', score:55, num:[85,11,4,30]},
    {id:3, name:'yasuda', age:38, gender:'male', score:45, num:[56,32,17,90]}
];

そして年齢が20以下と以上で配列を分けたいとします。
普通にループで書くとこのようになりますね。

var under20 = [];
var over20 = [];
var i;
for (i in member) {
    if (member[i].age < 20) {
        under20.push(member[i]);
    } else {
        over20.push(member[i]);
    }
}


    under20 -> [{id:1, name:'yasuda'...}]
    over20 -> [{id:2, name:'suzuki'...}, {id:3, name:'yasuda'...]

これをunderscore.jsを使って書くと...

var results = _.groupBy(member, function(item) {
    return item.age < 20;
});


results ->
    [
        true: [{id:1, name:'yasuda'...}]
        false: [{id:2, name:'suzuki'...}, {id:3, name:'yasuda'...]
    ]

短い!
変数が少ない!
ループの処理の検証もしなくて良い!
これは便利ですね。

いろんな関数があるみたいですが書き方が一緒で覚えやすい。

公式サイトの「Collection」にあるデータ収集関連の関数はだいたい書き方が一緒です。
まずアンダースコアを使って呼び出します。

_.groupBy()

そして引数にはデータとイテレータを渡します。

_.groupBy(data, function(){})

イテレータの引数に適当な変数名をつけると、処理中のオブジェクトにアクセスできるようになります。

_.groupBy(data, function(item){})

イテレータの内容は関数によって違います。
groupBy()の場合はグループ化のキーを返すようにしておきます。

_.groupBy(data, function(item){ item.age < 20; })

これを実行するとtrueまたはfalseでグループ化されたオブジェクトが返されます。

false: [
    {id: 1, name: 'yamada', age: 15},
    {id: 2, name: 'suzuki', age: 46}
],
true: [
    {id: 3, name: 'yasuda', age: 38}
]

いろいろ使ってみよう

公式サイトでは配列を使ったサンプルがたくさん紹介されています。
実際には単純な配列よりオブジェクトの配列のほうが使う機会が多いので、先ほどのmember配列をつかって試してみます。

member = [
    {id:1, name:'yamada', age:15, gender:'male', score:30, num:[11,12,21,10]},
    {id:2, name:'suzuki', age:46, gender:'female', score:55, num:[85,11,4,30]},
    {id:3, name:'yasuda', age:38, gender:'male', score:45, num:[56,32,17,90]}
];

使い方がちょっと...みたいな例もありますがご了承ください。ざっと読んでもらえると「こんなことができるんだ」というイメージを掴んでもらえるかと思います。

each

繰り返し処理をする

var result = 0;
_.each(member, function(item, i){
    result += item.score;
});

-> 130

map

配列を取り出す

var result = _.map(member, function(item, i){
    return item.id;
});

->[1,2,3]

reduce

合計

var map = _.map(member, function(item){ return item.score; });
var result = _.reduce(map, function(num1, num2){
    return num1 + num2;
});

->130

find

検索、一致したらストップ

var result = _.find(member, function(item){
    return item.age > 20;
});

->{"id":2,"name":"suzuki","age":46,"gender"...}

filter

検索、条件に合うものをすべて返す

var result = _.filter(member, function(item){
    return item.age > 20;
});

->[
    {"id":2,"name":"suzuki","age":46,"gender"...},
    {"id":3,"name":"yasuda","age":38,"gender"...}
]

findWhere

検索(オブジェクトで指定)、一致したらストップ

var result = _.findWhere(data, { gender:'male' });

->{"id":1,"name":"yamada","age":15,"gender"...}

filter

検索(オブジェクトで指定)、条件に合うものをすべて返す

var result = _.where(data, { gender:'male' });

->[
    {"id":1,"name":"yamada","age":15,"gender"...},
    {"id":3,"name":"yasuda","age":38,"gender"...}
]

reject

一致しないものを返す

var result = _.reject(member, function(item){
    return item.age == 15;
});

->[
    {"id":2,"name":"suzuki","age":46,"gender":...},
    {"id":3,"name":"yasuda","age":38,"gender":...}
]

every

すべて真かどうか

var score = _.map(data, function(item){ return item.score; });
return _.every(score, _.identity);

->true

some

真が含まれるか

var score = _.map(data, function(item){ return item.score; });
return _.some(score, _.identity);

->true

contains

値が含まれるか

var lists = _.map(data, function(item){ return item.age; });
return _.contains(lists, 46);

->true

pluck

プロパティを配列に

return _.pluck(data, 'name');

->['yamada','suzuki','yasuda']

sortBy

ソート

return _.sortBy(data, function(item){
return item.age;
});

->[
    {id:1, name:'yamada', age:15, gender:...},
    {id:3, name:'yasuda', age:38, gender:...},
    {id:2, name:'suzuki', age:46, gender:...}
]

min

最小値

return _.min(member, function(item){
    return _.min(item.num, function(n){
        return n;
    });
});

->{id:2, name:'suzuki', age:46, gender:...}

max

最小値

return _.max(data, function(item){
    return _.max(item.num, function(n){
        return n;
    });
});

->{id:2, name:'yasuda', age:38, gender:...}

count

カウント

var result = [];
_.each(member, function(item){
    // 条件に対するカウントがtrue/falseの配列で返るのでtrueだけ取り出す
    result.push(
        _.countBy(item.num, function(n){
            return n > 30;
        })[true]
    );
});

->[null,1,3]

shuffle

シャッフル

var result = _.shuffle(data);

->[
    {id:2, name:'suzuki', age:46, gender:...},
    {id:1, name:'yamada', age:15, gender:...},
    {id:3, name:'yasuda', age:38, gender:...}
]

size

return _.size(data);

->3

keys

キーを列挙

return _.keys(data[0]);

->['id','name','age','gender','score','num']

values

値を列挙

return _.values(data[0]);

->[1,'yamada',15,'male',30,11,12,21,10]

pairs

キーと値のペア

return _.pairs(member[0]);

->[
    ["id",1],
    ["name","yamada"],
    ["age",15],
    ["gender","male"],
    ["score",30],
    ["num",[11,12,21,10]]
]

invert

キーと値を入れ替える

return _.invert(data[0]);

->{
    "1":"id",
    "15":"age",
    "30":"score",
    "yamada":"name",
    "male":"gender",
    "11,12,21,10":"num"
}

extend

オブジェクトの追加

var result = _.extend(data[0], { section_id:1 }, { area_id:1 });

->{
    "id":1,
    "name":"yamada",
    "age":15,
    "gender":"male",
    "score":30,
    "num":[11,12,21,10],
    "section_id":1,
    "area_id":1
}

omit

オブジェクトの削除

var result = _.omit(data[0], 'gender', 'age', 'num');

->{
    "id":1,
    "name":"yamada",
    "score":30
}

has

オブジェクトが存在するか

var result = _.has(data[0], 'age');
->true

まとめ

長いことサンプルを書いてみましたが、他にも便利そうな関数がたくさんあります。
underscore.jsを使ったら、いちいち作っていた「idを検索する」「特定のキーでソートする」みたいな関数が減ってとても便利になりそうな気がします。



業界初のリスティング広告運用総合支援ツール Lisket(リスケット)

無料メルマガ

登録はたったの5秒!一週間分のコラムを毎週月曜にメールでお届けします。

Facebookもチェック