ikemonn's blog

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

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

jashkenas/underscore_.sampleを読んだ。

概要

_.sample(list, [n]

listからn個のランダムな値を取り出す。nが指定されない時は1つ取り出す。

var list = [1, 4, 15, 200, 3];
var x = _.sample(list);
console.log(x); // 4

ソースコード

  _.sample = function(obj, n, guard) {
    if (n == null || guard) {
      if (!isArrayLike(obj)) obj = _.values(obj);
      return obj[_.random(obj.length - 1)];
    }
    return _.shuffle(obj).slice(0, Math.max(0, n));
  };

第三引数のguardは_.mapと組み合わせて使う時にうまく動作するように指定してある。 isArrayLike(obj) = falseになるのは、listにオブジェクト等を渡した時。その場合は、プロパティvalueの中からランダムで値が取得される。

参考

jashkenas/underscore

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

jashkenas/underscore_.groupByを読んだ。

概要

_.groupBy(list, iteratee, [context]

listの各要素をiterateeを使ってグルーピングする。 iterateeが関数でない場合は、そのプロパティの値ごとにグルーピングする。

var list = [
    {age: 20, sex: "male", country: "JP", name: "hoge"},
    {age: 22, sex: "male", country: "US", name: "fuga"},
    {age: 20, sex: "female", country: "US", name: "piyo"},
    {age: 45, sex: "male", country: "JP", name: "HUGA"},
    {age: 20, sex: "male", country: "JP", name: "hoge"}
];
var x = _.groupBy(list, 'age');
console.log(x); // {20: [{age: 20, sex: "male", country: "JP", name: "hoge"},{age: 20, sex: "female", country: "US", name: "piyo"},{age: 20, sex: "male", country: "JP", name: "hoge"}], 22:[{age: 22, sex: "male", country: "US", name: "fuga"}], 45:[{age: 45, sex: "male", country: "JP", name: "HUGA"}]}

ソースコード

  var group = function(behavior) {
    return function(obj, iteratee, context) {
      var result = {};
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index) {
        var key = iteratee(value, index, obj);
        behavior(result, value, key);
      });
      return result;
    };
  };

  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
  });

listのそれぞれの要素にたいして、iterateeを実行して、その値をkeyとする。 その後、keyをプロパティとして結果の配列にpushする。 これを各要素分繰り返す。

参考

jashkenas/underscore

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

jashkenas/underscore_.sortByを読んだ。

概要

_.sortBy(list, iteratee, [context]

listの各要素をiterateeを使って評価した順にソートし、返す。 iterateeはプロパティの名前でも良い。

var list = [
    {age: 22, sex: "male", country: "US", name: "fuga"},
    {age: 45, sex: "male", country: "JP", name: "HUGA"},
    {age: 20, sex: "male", country: "JP", name: "hoge"}
];
var x = _.sortBy(list, 'age');
console.log(x); // [{age: 20, sex: "male", country: "JP", name: "hoge”},{age: 22, sex: "male", country: "US", name: "fuga"}, {age: 45, sex: "male", country: "JP", name: "HUGA"}]

ソースコード

  _.sortBy = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value: value,
        index: index,
        criteria: iteratee(value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria;
      var b = right.criteria;
      if (a !== b) {
        if (a > b || a === void 0) return 1;
        if (a < b || b === void 0) return -1;
      }
      return left.index - right.index;
    }), 'value');
  };

_.mapでvalue, index, iterateeを含むObjectを返す関数をlistの各要素に適用し、その値をソートする。 その後、pluckでvalueの値だけを取り出す。

.mapの引数である"value, index, list”は、.map内部の下記から来たもの。

results[index] = iteratee(obj[currentKey], currentKey, obj);

参考

jashkenas/underscore

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

jashkenas/underscore_.maxを読んだ。

概要

_.max(list, [iteratee], [context]

listの中の最大値を返す。 iterateeに関数が与えられると、その返り値が比較基準になる。 リストが空だと-Infinityが返るので、isEmptyを使って判定すること。

var list = [
    {age: 20, sex: "male", country: "JP", name: "hoge"},
    {age: 22, sex: "male", country: "US", name: "fuga"},
    {age: 20, sex: "female", country: "US", name: "piyo"},
    {age: 45, sex: "male", country: "JP", name: "HUGA"},
    {age: 20, sex: "male", country: "JP", name: "hoge"}
];
var x = _.max(list, function(elem){return elem.age;});
console.log(x); //  {age: 45, sex: "male", country: "JP", name: "HUGA"}

ソースコード

_.max = function(obj, iteratee, context) {
    var result = -Infinity, lastComputed = -Infinity,
        value, computed;
    if (iteratee == null && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value > result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index, list) {
        computed = iteratee(value, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = value;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

中で何をやっているかわかりやすい。使う機会が多そう。

参考

jashkenas/underscore

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

jashkenas/underscore_.pluckを読んだ。

概要

_.pluck(list, propertyName) 

listの中のpropertyNameで指定したプロパティの値を取得して配列で返す。 mapのよく使われる用途のラッパー。

var list = [
    {age: 20, sex: "male", country: "JP", name: "hoge"},
    {age: 22, sex: "male", country: "US", name: "fuga"},
    {age: 20, sex: "female", country: "US", name: "piyo"},
    {age: 45, sex: "male", country: "JP", name: "HUGA"},
    {age: 20, sex: "male", country: "JP", name: "hoge"}
];
var x = _.pluck(list, 'name');
console.log(x); // ["hoge", "fuga", "piyo", "HUGA", "hoge"]

ソースコード

_.pluck = function(obj, key) {
    return _.map(obj, _.property(key));
  };

_.propertyは、objの中からkeyの値を返す。 使えそう。

参考

jashkenas/underscore

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

jashkenas/underscore_.invokeを読んだ。

概要

_.invoke(list, methodName, *arguments

入れ子構造になっている配列の各要素の配列に対して関数を実行する。

_.invoke([[1, 4, 5, 2, 3], [10, 30, 20], [100, 78]], 'shift’); // [1, 10, 100]

ソースコード

_.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    var isFunc = _.isFunction(method);
    return _.map(obj, function(value) {
      var func = isFunc ? method : value[method];
      return func == null ? func : func.apply(value, args);
    });
  };

第三引数に、実行したい関数に対する引数を指定することもできる。 入れ子の配列の要素に対して、_.mapで関数を実行している。

参考

jashkenas/underscore

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

jashkenas/underscore_.containsを読んだ。

概要

_.contains(list, value, [fromIndex])

listにvalueがあればtrueを返す。

_.contains([1, 2, 3], 3); // true

ソースコード

  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
    if (!isArrayLike(obj)) obj = _.values(obj);
    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
    return _.indexOf(obj, item, fromIndex) >= 0;
  };

_.indexOfの中で、===を用いて比較しているのでオブジェクトを比較しようとするときは注意。

参考

jashkenas/underscore