-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Object-preserving map() function #220
Comments
That would be very handy. |
That seems like the same functionality could be obtained by slightly re-writing your iterator to an
Is this just a syntactic sugar? |
@greylurk Two reasons why your technique can't accomplish what is needed:
|
I think he meant |
What you proposed isn't a true object map, which would be able to specify the keys as well as the values of the returned object. There are several interesting versions of object mapping, none of which are mainstream enough to deserve to make it into Underscore proper -- all of which are quite useful as |
Would a mapValues be more generically useful? I find myself wanting to do that pretty frequently after a groupBy. |
I recently used an implementation like the following:
|
Completely OT: I propose a
|
yuchi - an "overscore" library, good move that. |
+1 for Overscore.js: Underscore.js for hipsters |
+1 for Overscore.js |
You forgot to return the obj. With this modification it works: _.mixin({
mapValues: function (input, mapper) {
return _.reduce(input, function (obj, v, k) {
obj[k] = mapper(v, k, input);
return obj;
}, {});
}
}); |
Apparently hipsters don't care about context. This update allows _.mapValues(list, iterator, this) to work, etc. _.mixin({
mapValues: function (input, mapper, context) {
return _.reduce(input, function (obj, v, k) {
obj[k] = mapper.call(context, v, k, input);
return obj;
}, {}, context);
}
}); Created a gist to track any further revisions: https://gist.github.com/3430971 |
I was about to submit a pull request for this and I am surprised to see that it has been discarded as "not mainstream". There are two major reasons for my surprise: (1) It is mainstream in the sense of being in basically all standard libraries for languages advanced enough to think about such things: Racket, Ruby, and Python share Underscore's behavior of (more or less) coercing dictionaries to a list first. Languages such as Java, Go, and C# are too first-order (in spirit, though at this point they could advance) to have equivalent libraries at all. Common Lisp doesn't even return a value... Basically the further back in time you go, the less like Underscore is a step ahead of Java but a step behind modern FP. Clojure is evidence that it does not require types, though they undoubtedly played a part in people eventually figuring this out. And this is figured out, which is my second reason. (2) This is the fundamental map over dictionaries in the sense of them being a functor - the concept that unifies all "container" data structures (used in random incorrect ways by C++, Ruby, and Prolog, so just don't go there). Those languages advanced enough to express this have done so: Haskell, Scala, Clojure. Someone even experimented with the idea in our own Javascript. As you say, there are several interesting maps on dictionaries. A good start would be Please reconsider, @jashkenas. +1 -- Kenn |
An alternative would be to implement the inverse of The Python built-in Example: function pairToObject(arr) {
var obj = {};
_.each(arr, function(el) {
var k = el[0];
var v = el[1];
obj[k] = v;
});
return obj;
} |
This is already included in the overloaded functionality of |
This would be super useful. |
@kennknowles, I'm totally with you. FWIW, here's the implementation I use: _.mixin({ mapValues: function (obj, f_val) {
return _.object(_.keys(obj), _.map(obj, f_val));
}}); I only include it since it's terser than the other implementations I've seen on this thread (though probably slower - would be cool to do some benchmarking) and also demonstrates how other Underscore functions compose to create |
That is an extremely cool implementation. |
+1 for reopening this. I constantly have to rewrite this. |
@jashkenas Do you have good links for the other types of object mappings you mentioned earlier? In my mind, there's probably also a |
+1 for Overscore.js I just needed this functionnality. Sad to find out it's not included. It's super useful! |
You might use: _.chain({abc: 123, xyz: '6', foo: '9'})
.map(function(val, key, obj) { return [key, parseInt(val,10)] })
.object()
.value(); |
+1 -- i also have to add it everywhere. It would be very nice to have it standard. After all, Underscore "provides a whole mess of useful functional programming helpers". |
+1 This would be a great addition to Underscore. Would you accept a pull request? |
There are some many issues of people running into this problem :( +1 for getting |
Would it be possible to add a
map()
-like function (since changing the current one would break things) which works exactly likemap()
but returns an object instead of an array if an object was passed?Example:
It might also make sense to have it return
[key, value]
tuples but just modifying the values might be sufficient for many cases.The text was updated successfully, but these errors were encountered: