-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reduce the runtime of pick
, fixes #285
#286
Conversation
…rties) to O(selection properties) Additional bonus, pick and pickBy are now implemented using map, curry and a helper function.
pick
, fixes #285
One thing, much of the code base uses function statements when possible. Can you change your function expressions to statements? Just to be consistent. Other than that, looks good to me. |
And possibly curry ...
return this.map(objectOnly(pickSelection));
...
return this.map(objectOnly(pickBySelection));
... |
currying ObjectOnly directly.
updated |
I should have mentioned this earlier, but can you add a test for inherited and non-enumerable properties? Make sure we catch all of them. |
good call, Before I make the change, are we in agreement that |
|
I believe I can make it work for |
…owned by the instance or any prototype object in its prototype chain. updated tests to account for selection of non-enumerable prototype member variables.
update |
var obj = x; // variable used to transverse prototype chain | ||
|
||
// function created here so we don't create one per loop | ||
var testAndAdd = function (prop) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function expression vs function statement again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, it is an optimization b/c it creates the function once instead of once per loop iteration. I placed a comment above it to note why this code is inconsistent with the rest of the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean. Couldn't you replace
var testAndAdd = function (prop) {
...
}
with
function testAndAdd(prop) {
...
}
Why would testAndAdd
be created once per loop iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh, got it I thought you meant put the declaration inside the loop as an anonymous function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
…re over writting it
…tions via `pick` or `pickBy`
All changes made, but I haven't run modified tests on an ES3 browser/engine. |
next(); | ||
var obj = x; // variable used to transverse prototype chain | ||
function testAndAdd (prop) { | ||
if (!(prop in out) && f(prop, x[prop])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would result in overridden properties being passed to f
. Example
function f(p, v) {
return v === 1;
}
var obj1 = {v: 1};
var obj2 = Object.create(obj1);
obj2.v = 2;
_([obj2]).pickBy(f).toArray(_.log) // => [{v: 1}]
In the reverse, it'll also disallow picking on default properties of objects, like hasOwnProperty
, but that's not as important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a test for the case I mentioned above? Call it "pickBy - overridden properties" or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subtle, but yes.
I'll fix it so overridden properties never make it to f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the test, but reverted my fix when I realized that it didn't originally fail. The reason why it doesn't fail is that the property may get tested twice, but always with the value relative to the object and not the prototype.
This is because testAndAdd is referrencing from the original object, obj2
here, rather than the prototype object, obj1
. So v
would always be 2
.
I'm going to go ahead and prevent it from testing a property multiple times.
if (err) { | ||
push(err); | ||
next(); | ||
var seen = {}; // prevents testing overridden properties multiple times. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think seen
should be Object.create(null)
so that properties from Object.prototype
get tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, added test the cover that case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't Object.create
fall prey to same problem as Object.getPrototypeOf
in that IE8 doesn't support it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the best way to deal with this? Put the Object.create
behind a if (es5)
check? Use strict seen[prop] === true
instead of prop in seen
? None of the Object.prototype
properties === true
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The best way to deal with it is to drop support for IE8. ;) Yeah, I guess we could do
var seen = isES5 ? Object.create(null) : {}
And then the strict equals test (that's very nice, I never knew about that before).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Fixed in 73a8cfe, though I don't have IE8 lying around, so I can't confirm.
… dictionary prototype member variable names automatically being skipped
Looks good. Thanks for the great work! |
reduce the runtime of `pick`, fixes #285
This is code fixes #285
It reduces the runtime of
pick
from O(object properties * selection properties) to O(selection properties) or simply from O(nm) to O(n)Additional bonus, pick and pickBy are now implemented using map, curry and a helper function.