I've re-implemented my own version of what I need but I suspect this is already included in underscore since it's so simple and so closely related to many other functions. But I can't think of what it should be called.
Basically, what I want is a version of _.pluck that works with objects and returns an object instead of an array (with its associated keys).
So, for instance, if I had an object like this:
elements: {
steam: {
temperature: 100,
color: 'orange',
state: 'gas'
},
water: {
temperature: 50,
color: 'blue',
state: 'liquid'
},
ice: {
temperature: 0,
color: 'white',
state: 'solid'
}
}
I'd want to call _.something(elements, 'temperature')
And have it return
{
steam: 100,
water: 50,
ice: 0
}
Instead of _.pluck(elements, 'temperature')
which returns
[100, 50, 0]
What is this transformation called and is it already included in underscore? I've written a quick version myself with jQuery's each loop since I'm more familiar with jQuery than underscore (included below) but would prefer to use one from the library if possible.
$.objPluck = function(obj, key) {
var ret = {};
$.each(obj, function(k, value) {
ret[k] = value[key];
});
return ret;
}
I've re-implemented my own version of what I need but I suspect this is already included in underscore since it's so simple and so closely related to many other functions. But I can't think of what it should be called.
Basically, what I want is a version of _.pluck that works with objects and returns an object instead of an array (with its associated keys).
So, for instance, if I had an object like this:
elements: {
steam: {
temperature: 100,
color: 'orange',
state: 'gas'
},
water: {
temperature: 50,
color: 'blue',
state: 'liquid'
},
ice: {
temperature: 0,
color: 'white',
state: 'solid'
}
}
I'd want to call _.something(elements, 'temperature')
And have it return
{
steam: 100,
water: 50,
ice: 0
}
Instead of _.pluck(elements, 'temperature')
which returns
[100, 50, 0]
What is this transformation called and is it already included in underscore? I've written a quick version myself with jQuery's each loop since I'm more familiar with jQuery than underscore (included below) but would prefer to use one from the library if possible.
$.objPluck = function(obj, key) {
var ret = {};
$.each(obj, function(k, value) {
ret[k] = value[key];
});
return ret;
}
Share
Improve this question
asked Aug 13, 2013 at 20:45
Brad DwyerBrad Dwyer
6,5048 gold badges49 silver badges71 bronze badges
3
-
There's the
Array.map
method which is basically what you're doing, but with an object – Ian Commented Aug 13, 2013 at 20:49 -
1
Is there a way to make
Array.map
preserve keys? – Brad Dwyer Commented Aug 13, 2013 at 20:50 -
1
I'm not sure I understand what you mean. And anyways, I was just referring to your initial concern of
But I can't think of what it should be called
. With arrays, I'd call this "mapping" – Ian Commented Aug 13, 2013 at 20:52
6 Answers
Reset to default 10There's no method to do exactly this in underscore 1.4.4, but if you want to stay in underscore, you can do
_.object(_.keys(elements), _.pluck(elements, 'temperature'))
Demo at jsfiddle courtesy of bfavaretto
As of underscore 1.8.3, this can be done succinctly with _.mapObject(elements, 'temperature');
.
Updated demo
Worth adding in here a solution that uses ES6 arrow functions, etc:
Object.keys(elements).map(f=>elements[f].temperature)
Note that this won't work on older javascript engines, but in node.js 0.12 with --harmony
it works great, or with node.js 4.x and later as well. I just tested this in Chrome 46 and it works fine.
It has the advantage of not needing any extra libraries such as underscore or lodash, but of course only works on new JS engines.
on lodash (similar to underscore) , you can use _.mapValues(elements,'temperature')
.
it's return {steam: 100, water: 50, ice: 0}
lodash ref : _.mapValues
by the way you can use _.mapKeys
to build object hash in one line
_.mapKeys(elements,'color') //{orange: Object, blue: Object, white: Object}
You don't need 3rd party libraries for easy stuff like this
// with a plain old for loop
const temps = {}
for (let key in data["elements"]) {
dikt[key] = temps["elements"][key]["temperature"]
}
return temps
// with a reduce
Object.keys(data['elements']).reduce((acc, key) => acc[key] = data['elements'][key]['temperature'] , temps)
In newer versions there is actually a built in function which does this.
If you give a string, instead of a function, to mapObject
, it will interpret that as a property name and behave as a "pluckObject
". Most functions are surprisingly liberal in what they accept.
> _.mapObject(elements,'temperature')
Object {steam: 100, water: 50, ice: 0}
If you want an explicit function for the purpose, you can look at how _.pluck
is implemented and write your own analogous version:
_.mixin({
pluckObject: function(obj, key) {
return _.mapObject(obj, _.property(key));
}
});
This is a bit redundant, but it makes your intentions clearer.
You can use a JavaScript for-in loop to iterate through the keys of the object:
var list = [];
// Iterate through each object key, and pick wanted the values.
for(var name in obj)
{
if (obj.hasOwnProperty(name) && name === "temperature")
{
list.push(obj[name]);
}
}
The above is a simplified example, but you should be able to easily modify to encapsulate it in a more generic function. Also, you don't really need to use JQuery here - native JavaScript implementation will be faster.
The obj.hasOwnProperty(name)
check is remended by JSLint.