From 3dd3af4a739caf5aa8c9a5f690f33f449d882e67 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 6 Nov 2013 20:45:24 -0800 Subject: [PATCH] Optimize `_.omit` for large arrays by leveraging `_.difference` which has optimizations for large arrays. --- dist/lodash.compat.js | 48 ++++++++++++++++++++--------------- dist/lodash.compat.min.js | 4 +-- dist/lodash.js | 36 +++++++++++++++----------- dist/lodash.min.js | 12 ++++----- dist/lodash.underscore.js | 25 ++++++++++-------- dist/lodash.underscore.min.js | 20 +++++++-------- lodash.js | 48 ++++++++++++++++++++--------------- 7 files changed, 108 insertions(+), 85 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 13a04c52a..02bdacaa6 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -566,10 +566,10 @@ (function() { var length = shadowedProps.length; while (length--) { - var prop = shadowedProps[length]; + var key = shadowedProps[length]; for (var className in nonEnumProps) { - if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], prop)) { - nonEnumProps[className][prop] = false; + if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { + nonEnumProps[className][key] = false; } } } @@ -679,8 +679,8 @@ props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; - for (var prop in new ctor) { props.push(prop); } - for (prop in arguments) { } + for (var key in new ctor) { props.push(key); } + for (key in arguments) { } /** * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). @@ -744,7 +744,7 @@ * @memberOf _.support * @type boolean */ - support.nonEnumArgs = prop != 0; + support.nonEnumArgs = key != 0; /** * Detect if properties shadowing those on `Object.prototype` are non-enumerable. @@ -2971,23 +2971,29 @@ * // => { 'name': 'fred' } */ function omit(object, callback, thisArg) { - var indexOf = getIndexOf(), - isFunc = typeof callback == 'function', - result = {}; + var result = {}; + if (typeof callback != 'function') { + var props = []; + forIn(object, function(value, key) { + props.push(key); + }); + props = difference(props, baseFlatten(arguments, true, false, 1)); - if (isFunc) { - callback = lodash.createCallback(callback, thisArg, 3); - } else { - var props = baseFlatten(arguments, true, false, 1); - } - forIn(object, function(value, key, object) { - if (isFunc - ? !callback(value, key, object) - : indexOf(props, key) < 0 - ) { - result[key] = value; + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + result[key] = object[key]; } - }); + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (!callback(value, key, object)) { + result[key] = value; + } + }); + } return result; } diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 718798a0e..439f110a8 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -39,8 +39,8 @@ jt(/x/)&&(jt=function(n){return typeof n=="function"&&ve.call(n)==K});var ur=we? },v.forEach=Dt,v.forEachRight=Nt,v.forIn=er,v.forInRight=function(n,t,e){var r=[];er(n,function(n,t){r.push(t,n)});var u=r.length;for(t=tt(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},v.forOwn=rr,v.forOwnRight=bt,v.functions=_t,v.groupBy=ar,v.indexBy=ir,v.initial=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return s(n,0,Fe(Re(0,u-r),u))},v.intersection=function(e){for(var r=arguments,u=r.length,a=-1,l=i(),f=-1,s=vt(),g=e?e.length:0,h=[],v=i();++a=_&&o(a?r[a]:v)}n:for(;++f(m?t(m,y):s(v,y))){for(a=u,(m||v).push(y);--a;)if(m=l[a],0>(m?t(m,y):s(r[a],y)))continue n;h.push(y)}}for(;u--;)(m=l[u])&&p(m);return c(l),c(v),h},v.invert=wt,v.invoke=function(n,t){var e=s(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,a=ne(typeof o=="number"?o:0);return Dt(n,function(n){a[++r]=(u?t:n[t]).apply(n,e)}),a},v.keys=Je,v.map=Bt,v.max=Pt,v.memoize=function(n,t){if(!jt(n))throw new fe;var e=function(){var r=e.cache,u=t?t.apply(this,arguments):b+arguments[0]; return je.call(r,u)?r[u]:r[u]=n.apply(this,arguments)};return e.cache={},e},v.merge=function(n){var t=arguments,e=2;if(!xt(n))return n;if("number"!=typeof t[2]&&(e=t.length),3r(a,e))&&(o[e]=n)}),o},v.once=function(n){var t,e;if(!jt(n))throw new fe;return function(){return t?e:(t=!0,e=n.apply(this,arguments),n=null,e)}},v.pairs=function(n){for(var t=-1,e=Je(n),r=e.length,u=ne(r);++t { 'name': 'fred' } */ function omit(object, callback, thisArg) { - var indexOf = getIndexOf(), - isFunc = typeof callback == 'function', - result = {}; + var result = {}; + if (typeof callback != 'function') { + var props = []; + forIn(object, function(value, key) { + props.push(key); + }); + props = difference(props, baseFlatten(arguments, true, false, 1)); - if (isFunc) { - callback = lodash.createCallback(callback, thisArg, 3); - } else { - var props = baseFlatten(arguments, true, false, 1); - } - forIn(object, function(value, key, object) { - if (isFunc - ? !callback(value, key, object) - : indexOf(props, key) < 0 - ) { - result[key] = value; + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + result[key] = object[key]; } - }); + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (!callback(value, key, object)) { + result[key] = value; + } + }); + } return result; } diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 0d7bde1dc..10eb6882d 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -35,12 +35,12 @@ return t?H(e,t):e},Z.createCallback=function(n,t,e){var r=typeof n;if(null==n||" var e=p(arguments,2);return ke(function(){n.apply(v,e)},t)},Z.difference=qt,Z.filter=Nt,Z.flatten=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=!1),null!=e&&(n=At(n,e,r)),it(n,t)},Z.forEach=Et,Z.forEachRight=Rt,Z.forIn=b,Z.forInRight=function(n,t,e){var r=[];b(n,function(n,t){r.push(t,n)});var u=r.length;for(t=ut(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},Z.forOwn=g,Z.forOwnRight=_t,Z.functions=bt,Z.groupBy=Ve,Z.indexBy=Ge,Z.initial=function(n,t,e){var r=0,u=n?n.length:0; if(typeof t!="number"&&null!=t){var o=u;for(t=Z.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return p(n,0,De(Ae(0,u-r),u))},Z.intersection=function(e){for(var r=arguments,u=r.length,i=-1,f=a(),p=-1,s=ht(),v=e?e.length:0,h=[],g=a();++i=_&&o(i?r[i]:g)}n:for(;++p(m?t(m,y):s(g,y))){for(i=u,(m||g).push(y);--i;)if(m=f[i],0>(m?t(m,y):s(r[i],y)))continue n;h.push(y)}}for(;u--;)(m=f[u])&&c(m);return l(f),l(g),h},Z.invert=dt,Z.invoke=function(n,t){var e=p(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,i=ne(typeof o=="number"?o:0); return Et(n,function(n){i[++r]=(u?t:n[t]).apply(n,e)}),i},Z.keys=ze,Z.map=At,Z.max=Dt,Z.memoize=function(n,t){function e(){var r=e.cache,u=t?t.apply(this,arguments):m+arguments[0];return de.call(r,u)?r[u]:r[u]=n.apply(this,arguments)}if(!wt(n))throw new le;return e.cache={},e},Z.merge=function(n){var t=arguments,e=2;if(!jt(n))return n;if("number"!=typeof t[2]&&(e=t.length),3r(i,e))&&(o[e]=n)}),o},Z.once=function(n){var t,e;if(!wt(n))throw new le; -return function(){return t?e:(t=!0,e=n.apply(this,arguments),n=null,e)}},Z.pairs=function(n){for(var t=-1,e=ze(n),r=e.length,u=ne(r);++te?Ae(0,r+e):De(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},Z.mixin=Xt,Z.noConflict=function(){return e._=se,this diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 851d22778..f8ead855f 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -1594,15 +1594,20 @@ * // => { 'name': 'fred' } */ function omit(object) { - var indexOf = getIndexOf(), - props = baseFlatten(arguments, true, false, 1), + var props = []; + forIn(object, function(value, key) { + props.push(key); + }); + props = difference(props, baseFlatten(arguments, true, false, 1)); + + var index = -1, + length = props.length, result = {}; - forIn(object, function(value, key) { - if (indexOf(props, key) < 0) { - result[key] = value; - } - }); + while (++index < length) { + var key = props[index]; + result[key] = object[key]; + } return result; } @@ -1667,9 +1672,9 @@ result = {}; while (++index < length) { - var prop = props[index]; - if (prop in object) { - result[prop] = object[prop]; + var key = props[index]; + if (key in object) { + result[key] = object[key]; } } return result; diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 40f4e75ac..4904a928f 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -27,13 +27,13 @@ return n};A(/x/)&&(A=function(n){return typeof n=="function"&&"[object Function] },u.chain=function(n){return n=new o(n),n.__chain__=!0,n},u.compact=function(n){for(var r=-1,t=n?n.length:0,e=[];++ru(i,f)){for(var a=t;--a;)if(0>u(r[a],f))continue n; i.push(f)}}return i},u.invert=j,u.invoke=function(n,r){var t=e(arguments,2),u=-1,o=typeof r=="function",i=n?n.length:0,f=Array(typeof i=="number"?i:0);return F(n,function(n){f[++u]=(o?r:n[r]).apply(n,t)}),f},u.keys=Ur,u.map=D,u.max=I,u.memoize=function(n,r){var t={};return function(){var e=r?r.apply(this,arguments):er+arguments[0];return Sr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}},u.min=function(n,r,t){var e=1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++or(t,u)&&(e[u]=n)}),e},u.once=function(n){var r,t;if(!A(n))throw new TypeError;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},u.pairs=function(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++rr?0:r);++nt?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=Z,u.noConflict=function(){return yr._=xr,this},u.noop=function(){},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Or(Wr()*(r-n+1))},u.reduce=$,u.reduceRight=W,u.result=function(n,r){if(n){var t=n[r];return A(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0; -return typeof r=="number"?r:Ur(n).length},u.some=C,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=b({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ur).source+"|"+(e.interpolate||ur).source+"|"+(e.evaluate||ur).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(or,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}"; -try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,m)},u.uniqueId=function(n){var r=++rr+"";return n?n+r:r},u.all=R,u.any=C,u.detect=B,u.findWhere=function(n,r){return P(n,r,!0)},u.foldl=$,u.foldr=W,u.include=N,u.inject=$,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=o;for(r=Q(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:nr; -return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=S(n)),null==r||t?n?n[0+Or(Wr()*(n.length-1-0+1))]:nr:(n=z(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.2.1",u.prototype.chain=function(){return this.__chain__=!0,this},u.prototype.value=function(){return this.__wrapped__},F("pop push reverse shift sort splice unshift".split(" "),function(n){var r=wr[n];u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this -}}),F(["concat","join","slice"],function(n){var r=wr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=!0),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yr._=u, define(function(){return u})):mr&&_r?dr?(_r.exports=u)._=u:mr._=u:yr._=u}).call(this); \ No newline at end of file +else r=Q(r,t,3),F(n,function(n,t,o){t=r(n,t,o),tr?0:r);++nt?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=Z,u.noConflict=function(){return yr._=xr,this},u.noop=function(){},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Or(Wr()*(r-n+1))},u.reduce=$,u.reduceRight=W,u.result=function(n,r){if(n){var t=n[r]; +return A(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Ur(n).length},u.some=C,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=b({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ur).source+"|"+(e.interpolate||ur).source+"|"+(e.evaluate||ur).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(or,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r +}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,m)},u.uniqueId=function(n){var r=++rr+"";return n?n+r:r},u.all=R,u.any=C,u.detect=B,u.findWhere=function(n,r){return P(n,r,!0)},u.foldl=$,u.foldr=W,u.include=N,u.inject=$,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; +if(typeof r!="number"&&null!=r){var i=o;for(r=Q(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:nr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=S(n)),null==r||t?n?n[0+Or(Wr()*(n.length-1-0+1))]:nr:(n=z(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.2.1",u.prototype.chain=function(){return this.__chain__=!0,this},u.prototype.value=function(){return this.__wrapped__},F("pop push reverse shift sort splice unshift".split(" "),function(n){var r=wr[n]; +u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this}}),F(["concat","join","slice"],function(n){var r=wr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=!0),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yr._=u, define(function(){return u})):mr&&_r?dr?(_r.exports=u)._=u:mr._=u:yr._=u}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index 3c69b34f4..7a472348d 100644 --- a/lodash.js +++ b/lodash.js @@ -566,10 +566,10 @@ (function() { var length = shadowedProps.length; while (length--) { - var prop = shadowedProps[length]; + var key = shadowedProps[length]; for (var className in nonEnumProps) { - if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], prop)) { - nonEnumProps[className][prop] = false; + if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { + nonEnumProps[className][key] = false; } } } @@ -679,8 +679,8 @@ props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; - for (var prop in new ctor) { props.push(prop); } - for (prop in arguments) { } + for (var key in new ctor) { props.push(key); } + for (key in arguments) { } /** * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). @@ -744,7 +744,7 @@ * @memberOf _.support * @type boolean */ - support.nonEnumArgs = prop != 0; + support.nonEnumArgs = key != 0; /** * Detect if properties shadowing those on `Object.prototype` are non-enumerable. @@ -2989,23 +2989,29 @@ * // => { 'name': 'fred' } */ function omit(object, callback, thisArg) { - var indexOf = getIndexOf(), - isFunc = typeof callback == 'function', - result = {}; + var result = {}; + if (typeof callback != 'function') { + var props = []; + forIn(object, function(value, key) { + props.push(key); + }); + props = difference(props, baseFlatten(arguments, true, false, 1)); - if (isFunc) { - callback = lodash.createCallback(callback, thisArg, 3); - } else { - var props = baseFlatten(arguments, true, false, 1); - } - forIn(object, function(value, key, object) { - if (isFunc - ? !callback(value, key, object) - : indexOf(props, key) < 0 - ) { - result[key] = value; + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + result[key] = object[key]; } - }); + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (!callback(value, key, object)) { + result[key] = value; + } + }); + } return result; }