Underscore.jsおさらい3(Arrays)

first _.first(array, [n])

先頭の要素を返す。shiftと違い非破壊的。
nを指定すると先頭からn個分の要素を配列で返す。

initial _.initial(array, [n])

最後の要素を除いた配列を返す。
nを指定すると後ろからn個分除いた残りを返す。

_.initial([5, 4, 3, 2, 1]);
=> [5, 4, 3, 2]


last _.last(array, [n])

firstの逆。最後の要素を返す。

rest _.rest(array, [index])

initialの逆。最初の要素を除いた配列を返す。
多分first~restは、非破壊的なshift、popのニーズから作ったものだろう。

compact _.compact(array)

配列から「!hoge」== trueな要素を除いた配列を返す。

_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]


flatten _.flatten(array, [shallow])

多次元配列の全要素を1次元配列にする。
shallowにtrueを指定すると全て平らにせず、次元を1つ減らすだけで止める。

_.flatten([1, [2], [3, [[4]]]]);
=> [1, 2, 3, 4];

_.flatten([1, [2], [3, [[4]]]], true);
=> [1, 2, 3, [[4]]];


without _.without(array, *values)

valuesに指定した以外の値だけを含んだ配列を返す。
valuesにArrayオブジェクト指定はできないので、そんな時はdifferenceで。

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
=> [2, 3, 4]


union _.union(*arrays)

重複要素は除きつつ配列を結合する。

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]


intersection _.intersection(*arrays)

全ての配列に含まれる要素だけを取り出す。

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]


difference _.difference(array, *others)

withoutに似ているが、除外条件を配列で指定できる。

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]


uniq _.uniq(array, [isSorted], [iteratee])

配列をユニーク化する。
ソート済みの配列であればisSortedにtrueを指定すれば処理が早くなる。
要素の一致条件は「===」なので、オブジェクトの配列の場合はデフォルトではユニーク化されない。
iterateeに一致条件の値を指定すればユニーク化できる。プロパティの文字列指定も可。

_.uniq([1, 2, 1, 4, 1, 3]);
=> [1, 2, 4, 3]

var array = [{id:1}, {id:2}, {id:3}, {id:1}, {id:2}];
_.uniq(array, function(element){ return element.id; });
=>[{id:1}, {id:2}, {id:3}]
_.uniq(array, 'id');
=>[{id:1}, {id:2}, {id:3}]


zip _.zip(*arrays)

配列をマージする。もしlengthが異なっていれば、undefinedで穴埋めされる。
多次元配列に値を持っている場合は、_.zip.applyで幸せになれる、とわざわざドキュメントに書いているのに、unzipで同じことができる謎。
unzipは一度削除されて復活されたから、説明がそのまま残っているのだと思われる。
zipのソースを見ると、unzipに処理を丸投げしている。

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
_.zip(['moe', 'larry', 'curly'], [30, 40], [true, false, false]);
=> [["moe", 30, true], ["larry", 40, false], ["curly", undefined, false]]


unzip _.unzip(*arrays)

unとついていてもzipの逆ではなく、多次元配列をzipする。
引数が*arraysになっているが、多分表記が誤っている。第一引数の多次元配列しか処理されない。

_.unzip([['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]])
=> ["moe", 30, true], ["larry", 40, false], ["curly", 50, false]


object _.object(list, [values])

object化、というかハッシュ配列化してくれる。多次元配列の場合はvaluesは不要。
listの各要素がkeyになるので、valuesの要素数の方が多ければvaluesの多い分は無視される。
listの方が多ければ、valueにundefinedが入る。

_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
=> {moe: 30, larry: 40, curly: 50}

_.object([['moe', 30], ['larry', 40], ['curly', 50]]);
=> {moe: 30, larry: 40, curly: 50}


indexOf _.indexOf(array, value, [isSorted])

該当要素の番号を返すおなじみのやつ。だが基本使わないはず。Array.indexOfがECMAScript 5で実装されている。
(IE8以前を使っているような古代人は相手にしない)
ソート済みの場合はisSortedにtrue指定で処理が早くなるので、使うとすればそこぐらいか。

lastIndexOf _.lastIndexOf(array, value, [fromIndex])

indexOfの最後から版。isSortedオプションも無いので、使うことはないだろう。

sortedIndex _.sortedIndex(list, value, [iteratee], [context])

indexOfのもしもボックス版。
ソート済みのlistに対して、もしvalueが入るなら何番目かを返してくる。
オブジェクトの配列ならiterateeで条件を指定する。プロパティの文字列指定も化。

_.sortedIndex([10, 20, 30, 40, 50], 35);
=> 3

var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}];
_.sortedIndex(stooges, {name: 'larry', age: 50}, 'age');
=> 1


findIndex _.findIndex(array, predicate, [context])

indexOfが固定値の検索だが、findIndexは条件を関数で指定できる。
predicateにkey : valueのオブジェクトを指定して、条件を含むオブジェクトの検索も可。
findWhereのindexOf版みたいな感じになる。

_.findIndex([4, 6, 7, 12], function(num){ return num % 2 == 1; });
=> 2

var users = [{'id': 1, 'name': 'Bob', 'last': 'Brown'},
             {'id': 2, 'name': 'Ted', 'last': 'White'},
             {'id': 3, 'name': 'Frank', 'last': 'James'},
             {'id': 4, 'name': 'Ted', 'last': 'Jones'}];
_.findIndex(users, {name: 'Ted'});
=> 1
_.findIndex(users, {name: 'Ted', last: 'Jones'});
=> 3


findLastIndex _.findLastIndex(array, predicate, [context])

findIndexを後ろから。

range _.range([start], stop, [step])

指定した範囲までの連番が入った配列を作ってくれる。

_.range(10);
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11);
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5);
=> [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1);
=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0);
=> []

Array終了。