diff --git a/README.md b/README.md index 933315a..0bf65e7 100644 --- a/README.md +++ b/README.md @@ -312,6 +312,16 @@ var isObject = require('101/is-object'); [{}, { foo: 1 }, 100].map(isObject); // [true, true, false] ``` +## isRegExp + +Check if a value is an instance of RegExp + +```js +var isRegExp = require('101/is-regexp'); + +[new RegExp('.*'), /.*/, {}, 1].map(isRegExp); // [true, true, false, false] +``` + ## isString Functional version of val typeof 'string' @@ -411,7 +421,7 @@ var passAny = require('101/pass-any'); ## pick Returns a new object with the specified keys (with key values from obj). -Supports partial functionality (great with array functions, like map). +Supports regular expressions and partial functionality (great with array functions, like map). ```js var pick = require('101/pick'); @@ -421,6 +431,7 @@ var obj = { }; pick(obj, 'foo'); // { foo: 1 } +pick(obj, RegExp('oo$')); // { foo: 1 } pick(obj, ['foo']); // { foo: 1 } pick(obj, ['foo', 'bar']); // { foo: 1, bar: 2 } diff --git a/is-regexp.js b/is-regexp.js new file mode 100644 index 0000000..f99522b --- /dev/null +++ b/is-regexp.js @@ -0,0 +1,15 @@ +/** + * @module 101/is-regexp + */ + +/** + * Check if a value is an instance of RegExp + * @function module:101/is-regexp + * @param {*} val - value checked to be an instance of RegExp + * @return {boolean} Whether the value is an object or not + */ + +module.exports = function isRegExp (val) { + return Object.prototype.toString.call(val) == '[object RegExp]'; +}; + diff --git a/package.json b/package.json index 3000e92..3192006 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "common javascript utils that can be required selectively that assume es5+", "main": "index.js", "scripts": { - "test": "lab -c test", + "test": "lab -c -t 100 test", "test-watch": "nodemon --exec lab -c test" }, "repository": { diff --git a/pick.js b/pick.js index 1d94ae6..82d271a 100644 --- a/pick.js +++ b/pick.js @@ -3,13 +3,14 @@ */ var isObject = require('./is-object'); +var isRegExp = require('./is-regexp'); /** * Returns a new object with the specified keys (with key values from obj). * When only keys are specified pick returns a partial-function which accepts obj. * @function module:101/pick * @param {object} [obj] - object whose keys are picked - * @param {string|array} keys... - keys which will be taken from obj (can be specifieds as args (strings and/or arrays) + * @param {string|regexp|array} keys... - keys which will be taken from obj, can be specifieds as args (strings, regular epxressions, and/or arrays) * @return {object|function} Object with only the keys specified from the original obj or Partial-function pick (which accepts obj) and returns an object */ module.exports = function () { @@ -37,8 +38,16 @@ function pick (obj, args) { function copy (from, to) { return function (key) { - if (key in from) { - to[key] = from[key]; + if (isRegExp(key)) { + Object.keys(from).forEach(function(keyFrom) { + if (key.test(keyFrom)) { + to[keyFrom] = from[keyFrom]; + } + }); + } else { + if (key in from) { + to[key] = from[key]; + } } }; -} \ No newline at end of file +} diff --git a/test/test-isregexp.js b/test/test-isregexp.js new file mode 100644 index 0000000..9110c05 --- /dev/null +++ b/test/test-isregexp.js @@ -0,0 +1,30 @@ +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); + +var describe = lab.describe; +var it = lab.it; +var expect = Lab.expect; + +var isRegExp = require('../is-regexp'); + +describe('isRegExp', function () { + it('should return true for instance of RegExp', function(done) { + var regexp = new RegExp('.*'); + expect(isRegExp(regexp)).to.be.true; + expect(isRegExp(/.*/)).to.be.true; + done(); + }); + + it('should return false for non-regexp', function(done) { + expect(isRegExp({})).to.be.false; + expect(isRegExp(['foo'])).to.be.false; + expect(isRegExp('foo')).to.be.false; + expect(isRegExp(101)).to.be.false; + expect(isRegExp(function () {})).to.be.false; + expect(isRegExp(null)).to.be.false; + expect(isRegExp(undefined)).to.be.false; + expect(isRegExp(new String('hey'))).to.be.false; + expect(isRegExp(new Number(101))).to.be.false; + done(); + }); +}); diff --git a/test/test-pick.js b/test/test-pick.js index bcca57d..ff08e95 100644 --- a/test/test-pick.js +++ b/test/test-pick.js @@ -40,6 +40,32 @@ describe('pick', function () { }); expect(pick(obj)).to.eql({}); expect(pick(obj, [])).to.eql({}); + expect(pick(obj, RegExp('a'))).to.eql({ + bar: 1 + }); + expect(pick(obj, RegExp('a'), 'foo')).to.eql({ + foo: 1, + bar: 1 + }); + expect(pick(obj, [RegExp('q|b')], 'bar')).to.eql({ + bar: 1, + qux: 1 + }); + expect(pick(obj, [RegExp('q'), RegExp('f')], ['bar'])).to.eql({ + foo: 1, + bar: 1, + qux: 1 + }); + expect(pick(obj, [RegExp('q'), 'foo'], 'bar')).to.eql({ + foo: 1, + bar: 1, + qux: 1 + }); + expect(pick(obj, [RegExp('x$'), 'foo'], [RegExp('b')])).to.eql({ + foo: 1, + bar: 1, + qux: 1 + }); done(); }); it('should pick keys from objects in an array when used with map', function(done) { @@ -135,6 +161,70 @@ describe('pick', function () { bar: 3 } ]); + expect(objs.map(pick(RegExp('q|g')))).to.eql([ + {}, + { + qux: 2 + }, + { + goo: 3 + } + ]); + expect(objs.map(pick(RegExp('BAR', 'i'), 'foo'))).to.eql([ + { + bar: 1 + }, + { + foo: 2, + bar: 2 + }, + { + foo: 3, + bar: 3 + } + ]); + expect(objs.map(pick([RegExp('b')], 'foo'))).to.eql([ + { + bar: 1 + }, + { + foo: 2, + bar: 2 + }, + { + foo: 3, + bar: 3 + } + ]); + expect(objs.map(pick([RegExp('b'), 'qux'], ['foo']))).to.eql([ + { + bar: 1 + }, + { + bar: 2, + foo: 2, + qux: 2 + }, + { + foo: 3, + bar: 3 + } + ]); + expect(objs.map(pick([RegExp('b'), RegExp('^f')], [RegExp('oo$')]))).to.eql([ + { + bar: 1 + }, + { + bar: 2, + foo: 2 + }, + { + bar: 3, + foo: 3, + koo: 3, + goo: 3 + } + ]); expect(objs.map(pick())).to.eql([ {}, {}, {} ]);