ikemonn's blog

技術ネタをちょこちょこと

【Underscore.js】_.unionを読んだ

jashkenas/underscore_.unionを読んだ。

概要

_.union(*arrays)

引数で与えられた配列を一つにまとめる。 その際に重複した値は削除され、重複した値がない配列となって返される。

var x = _.union([1, 10, 10, 3], [3 ,190]);
console.log(x); // [1, 10, 3, 190]

ソースコード

  _.union = function() {
    return _.uniq(flatten(arguments, true, true));
  };



 _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = cb(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = getLength(array); i < length; i++) {
      var value = array[i],
          computed = iteratee ? iteratee(value, i, array) : value;
      if (isSorted) {
        if (!i || seen !== computed) result.push(value);
        seen = computed;
      } else if (iteratee) {
        if (!_.contains(seen, computed)) {
          seen.push(computed);
          result.push(value);
        }
      } else if (!_.contains(result, value)) {
        result.push(value);
      }
    }
    return result;
  };

flattenで与えられた引数の入れ子をなくし、_.uniqで重複した値を削除している。

参考

jashkenas/underscore

【Underscore.js】_.withoutを読んだ

jashkenas/underscore_.withoutを読んだ。

概要

_.without(array, *values) 

arrayからvaluesを除いた配列を返す。

var list = [1, 10, 7, 190, 43];
var x = _.without(list, 7, 43 ,190);
console.log(x); // [1, 10]

ソースコード

_.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

_.difference = function(array) {
    var rest = flatten(arguments, true, true, 1);
    return _.filter(array, function(value){
      return !_.contains(rest, value);
    });
  };

flattenで、第二引数以降の値を取り出している。 その後、.filterと.containsを用いて、配列に値が含まれているかをチェックしている。

参考

jashkenas/underscore

【Underscore.js】_.flattenを読んだ

jashkenas/underscore_.flattenを読んだ。

概要

_.flatten(array, [shallow])

入れ子になっている配列を、一次元の配列に変換する。 shallowがtrueの時は、一つだけ入れ子をなくす。

list = [1, 10, 7, [190, 43], [[1]]];
var x = _.flatten(list);
console.log(x); // [1, 10, 7, 190, 43, 1]

ソースコード

 var flatten = function(input, shallow, strict, startIndex) {
    var output = [], idx = 0;
    for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
      var value = input[i];
      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
        //flatten current level of array or arguments object
        if (!shallow) value = flatten(value, shallow, strict);
        var j = 0, len = value.length;
        output.length += len;
        while (j < len) {
          output[idx++] = value[j++];
        }
      } else if (!strict) {
        output[idx++] = value;
      }
    }
    return output;
  };

  // Flatten out an array, either recursively (by default), or just one level.
  _.flatten = function(array, shallow) {
    return flatten(array, shallow, false);
  }

shallowを指定しない場合は、下記のコードで再帰的に入れ子を1つずつなくしていっている。

if (!shallow) value = flatten(value, shallow, strict);

参考

jashkenas/underscore

【Underscore.js】_.compactを読んだ

jashkenas/underscore_.compactを読んだ。

概要

_.compact(array) 

配列の中のfalsyな値(false, null, 0, "", undefined, NaN)を除いて返す。

var list = [0, null, undefined, 1, 2, "null", "", NaN];
var x = _.compact(list);
console.log(x); // [1, 2, "null"]

ソースコード

  _.compact = function(array) {
    return _.filter(array, _.identity);
  };

 _.identity = function(value) {
    return value;
  };

_.filter = _.select = function(obj, predicate, context) {
    var results = [];
    predicate = cb(predicate, context);
    _.each(obj, function(value, index, list) {
      if (predicate(value, index, list)) results.push(value);
    });
    return results;
  };

.identityは引数をそのまま返すだけの関数。 それを.filterの引数に与えて実行することで、_.filter内の下記のif文でfalsyは弾かれて結果に入らなくなる。

// predicate = _.identity
if (predicate(value, index, list)) results.push(value);

ただ値を返すだけの_.identityが、他の関数と組み合わさって便利になってるのを見て良いなと思った。

参考

jashkenas/underscore

【Underscore.js】_.initialを読んだ

jashkenas/underscore_.initialを読んだ。

概要

_.initial(array, [n]

末尾からn個を除くすべての配列の要素を返す。 nが指定されていない時は、arrayの最後の要素以外のすべてを返す。

var list = [1, 10, 7, 190, 43];
var x = _.initial(list);
console.log(x); // [1, 10, 7, 190]

ソースコード

 _.initial = function(array, n, guard) {
    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
  };

guardは_.mapと併用して使うときのためにある。 arugumentsに対して使うときに便利そう。

参考

jashkenas/underscore

【Underscore.js】_.partitionを読んだ

jashkenas/underscore_.partitionを読んだ。

概要

_.partition(array, predicate) 

listをpredicateを満たすものと満たさないものの2つ配列に分割して返す。

var list = [1, 10, 7, 190, 43];var x = _.partition(list, function(num) { return num % 2 === 0;});
console.log(x); // [[10, 190], [1, 7, 43]]

ソースコード

_.partition = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var pass = [], fail = [];
    _.each(obj, function(value, key, obj) {
      (predicate(value, key, obj) ? pass : fail).push(value);
    });
    return [pass, fail];
  };

predicateを満たすものと満たさないものを配列にpushして返す。

参考

jashkenas/underscore

【Underscore.js】_.toArrayを読んだ

jashkenas/underscore_.toArrayを読んだ。

概要

_.toArray(list)

listを配列にして返す。

var list = {age: 20, sex: "male", country: "JP", name: "hoge"};
var x = _.toArray(list);
console.log(x); // [20, "male", "JP", "hoge"]

ソースコード

 _.toArray = function(obj) {
    if (!obj) return [];
    if (_.isArray(obj)) return slice.call(obj);
    if (isArrayLike(obj)) return _.map(obj, _.identity);
    return _.values(obj);
  };

argumentsのような配列っぽいものも、配列にして返してくれるのでargumentsに対して何か処理をするときにも使える。

参考

jashkenas/underscore