8
4

More than 5 years have passed since last update.

JavaScriptにもflatMapを!

Last updated at Posted at 2013-09-23

この記事を読んでJavaScriptにもflatMapが欲しくなったので作ってみた。

まずは普通の関数

func_flatMap.js
function flatMap(xs, f) {
  return xs.reduce(function (ys, x) {
    return ys.concat(f(x));
  }, []);
}

//=> [4, 12, 20, 28, 36]
console.log(flatMap([1,2,3,4,5,6,7,8,9,10], function (x) {
  return x % 2 === 1 ? [x << 2] : [];
}));

ネストがアレです。

次はArray.prototypeの拡張

prototype_flatMap.js
Object.defineProperty(Array.prototype, 'flatMap', {
  value: function (f, self) {
    self = self || this;
    return this.reduce(function (ys, x) {
      return ys.concat(f.call(self, x));
    }, []);
  },
  enumerable: false,
});

//=> [4, 12, 20, 28, 36]
console.log([1,2,3,4,5,6,7,8,9,10].flatMap(function (x) {
  return x % 2 === 1 ? [x << 2] : [];
}));

列挙しないようにしてますけど、他のライブラリと競合すう可能性ありそうだな……。

最後に、underscore.jsでやってみました。

js;underscore_flatMap.js

var
_ = require('underscore');

var
flatMap = _.flatMap = _.concatMap = function (xs, f, self) {;
  return _.reduce(xs, function (ys, x) {
    return ys.concat(f.call(self, x));
  }, []);
};

_.each(['flatMap', 'concatMap'], function (name) {
  _.prototype[name] = function (f, self) {
    return _(flatMap(this.value(), f, self));
  };
});

//さっきよりシンプルになったように見えるのは_.rangeのおかげ?
console.log(_.flatMap(_.range(1, 11), function (x) {
  return x % 2 === 1 ? [x << 2] : [];
}));

//こういう風にも書ける
console.log(_(_.range(1, 11)).flatMap(function (x) {
  return x % 2 === 1 ? [x << 2] : [];
}).value());

というか何でunderscore.jsにはflatMapが無いのでしょう? 解せません。

あと、ここに載せたコードは煮るなり焼くなり好きにしてやって下さい。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4