什么是与 _.pluck 等价的对象操作?

9
我已经重新实现了我需要的内容,但是我怀疑这个功能已经包含在underscore中了,因为它非常简单并与许多其他函数密切相关。但是我想不出它应该叫什么。
基本上,我想要的是一个能够处理对象并返回对象而不是数组(带有其关联键)的_.pluck版本。
例如,如果我有这样一个对象:
elements: {
    steam: {
        temperature: 100,
        color: 'orange',
        state: 'gas'
    },
    water: {
        temperature: 50,
        color: 'blue',
        state: 'liquid'
    },
    ice: {
        temperature: 0,
        color: 'white',
        state: 'solid'
    }
}

我希望调用_.something(elements, 'temperature')

并获得以下返回结果

{
    steam: 100,
    water: 50,
    ice: 0
}

与其使用_.pluck(elements, 'temperature')返回的结果为

[100, 50, 0]

这个转换被称为什么,它是否已经包含在underscore中?我用jQuery的each循环自己写了一个简单版本,因为我比较熟悉jQuery(如下所示),但如果可能的话,我更愿意使用库中的一个。
$.objPluck = function(obj, key) {
    var ret = {};
    $.each(obj, function(k, value) {
        ret[k] = value[key];
    });
    return ret;
}

有一个 Array.map 方法,基本上就是你正在做的事情,但是针对对象。 - Ian
1
有没有办法让 Array.map 保留键名? - Brad Dwyer
1
我不确定我理解你的意思。无论如何,我只是在提到你最初关心的“但我想不出它应该被称为什么”。对于数组,我会称之为“映射”。 - Ian
6个回答

10

在underscore 1.4.4中没有现成的方法可以精确实现这一点,但如果你想继续使用underscore,你可以这样做:

_.object(_.keys(elements), _.pluck(elements, 'temperature'))

Demo at jsfiddle,由bfavaretto提供


从underscore1.8.3开始,可以使用_.mapObject(elements, 'temperature');简洁地完成此操作。

更新的演示


2
我本来也要发布完全相同的代码。这里有一个 jsfiddle 来演示它:http://jsfiddle.net/PfZwx/ - bfavaretto
@bfavaretto 给你的评论点了赞,因为我忘记包含我的代码演示。我还看到了你的帖子上线了4秒钟!:-P - Evan Davis
实际上是12秒钟! :) - bfavaretto
谢谢!我甚至没有考虑过使用多个_函数的组合。 - Brad Dwyer
1
对于较新版本的underscore,有一个可以直接执行此操作的函数:mapObject。这相当于lodash中的mapValues - Hjulle

8

这里值得一提的是,有一个使用ES6箭头函数等解决方案:

Object.keys(elements).map(f=>elements[f].temperature)

请注意,这在较旧的JavaScript引擎上不起作用,但在带有 --harmony 的node.js 0.12中运行良好,或者在node.js 4.x及更高版本中也可以。我刚在Chrome 46中测试过,它能正常工作。
它的优点是不需要任何额外的库,如underscore或lodash,但当然只适用于新的JS引擎。

1
使用非ES6符号:Object.keys(elements).map(function(f) {return elements[f].temperature}) - egidiocs
1
但是这样有什么乐趣呢?;-) - taxilian
这是一个有用的技巧,但请注意,它不会返回提问者想要的对象,它只返回一个没有元素名称的数组。 - Nate

3
在lodash(类似于underscore)中,您可以使用_.mapValues(elements,'temperature')。它会返回{steam: 100, water: 50, ice: 0}。 lodash参考:_.mapValues 顺便提一下,您还可以使用_.mapKeys在一行中构建对象哈希:_.mapKeys(elements,'color') //{orange: Object, blue: Object, white: Object}

1
你不需要第三方库来完成像这样的简单任务。
// 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)

0
在较新的版本中,实际上有一个内置的函数可以执行此操作。
如果您向mapObject传递一个字符串而不是函数,则它将将其解释为属性名称并表现为“pluckObject”。大多数函数都非常自由地接受任何内容。
> _.mapObject(elements,'temperature')
Object {steam: 100, water: 50, ice: 0}

如果要实现一个明确的函数,您可以查看 _.pluck 是如何 实现 的,并编写您自己类似的版本:

_.mixin({
  pluckObject: function(obj, key) {
    return _.mapObject(obj, _.property(key));
  }
});

这有点冗余,但它可以让你的意图更清晰。


0
你可以使用 JavaScript for-in 循环 遍历对象的键:
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]);
    }
}

以上是一个简化的示例,但您应该能够轻松修改以将其封装在更通用的函数中。此外,在这里您不需要真正使用JQuery-本机JavaScript实现将更快。 obj.hasOwnProperty(name)检查由JSLint推荐。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接