144

underscore.js 中的map函数,如果使用 javascript 对象调用,则返回从对象值映射的值数组。

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]

有没有办法让它保留密钥?即,我想要一个返回的函数

{one: 3, two: 6, three: 9}
4

12 回答 12

245

下划线

Underscore 提供了_.mapObject映射值和保留键的功能。

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


洛达什

Lodash 提供了一个函数_.mapValues来映射值并保留键。

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO

于 2013-09-26T08:43:45.403 回答
57

我设法在 lodash 中找到了所需的函数,lodash 是一个类似于下划线的实用程序库。

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg])

通过回调运行对象的每个自己的可枚举属性,创建具有与对象相同的键和值的对象。回调绑定到 thisArg 并使用三个参数调用;(值、键、对象)。

于 2014-07-01T02:34:49.937 回答
19

var mapped = _.reduce({ one: 1, two: 2, three: 3 }, function(obj, val, key) {
    obj[key] = val*3;
    return obj;
}, {});

console.log(mapped);
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

于 2014-08-27T11:43:52.223 回答
15

这个版本的纯 JS ( ES6 / ES2015 ) 怎么样?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));

jsbin

如果你想递归地映射一个对象(映射嵌套的 obj),可以这样做:

const mapObjRecursive = (obj) => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]);
    else obj[key] = obj[key] * 3;
  });
  return obj;
};

jsbin

由于ES7 / ES2016你可以使用Object.entries而不是Object.keys这样:

let newObj = Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * 3})));

ES2019 开始,您可以使用 Object.fromEntries.

let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => ([k, v * 3])))
于 2016-08-08T11:53:15.080 回答
13

我知道这是旧的,但现在下划线有一个新的对象地图:

_.mapObject(object, iteratee, [context]) 

您当然可以为数组和对象构建灵活的映射

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}
于 2015-04-24T13:11:19.463 回答
5

I know it's been a long time, but still the most obvious solution via fold (aka reduce in js) is missing, for the sake of completeness i'll leave it here:

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}
于 2018-02-28T11:01:56.873 回答
3

_.map返回一个数组,而不是一个对象。

如果你想要一个对象,你最好使用不同的函数,比如each; 如果你真的想使用地图,你可以这样做:

Object.keys(object).map(function(value, index) {
   object[value] *= 3;
})

但这很令人困惑,当看到map人们期望有一个数组作为结果然后用它做一些事情时。

于 2013-09-26T08:36:29.157 回答
3

我认为您需要一个mapValues函数(将函数映射到对象的值上),这很容易自己实现:

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};
于 2014-03-28T02:58:07.490 回答
2
const mapObject = (obj = {}, mapper) =>
  Object.entries(obj).reduce(
    (acc, [key, val]) => ({ ...acc, [key]: mapper(val) }),
    {},
  );
于 2019-09-25T10:41:32.657 回答
0

下划线地图错误的混合修复:P

_.mixin({ 
    mapobj : function( obj, iteratee, context ) {
        if (obj == null) return [];
        iteratee = _.iteratee(iteratee, context);
        var keys = obj.length !== +obj.length && _.keys(obj),
            length = (keys || obj).length,
            results = {},
            currentKey;
        for (var index = 0; index < length; index++) {
          currentKey = keys ? keys[index] : index;
          results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
        }
        if ( _.isObject( obj ) ) {
            return _.object( results ) ;
        } 
        return results;
    }
}); 

一个简单的解决方法,保留正确的键并作为对象返回它仍然使用与我客人相同的方式,您可以使用此函数来覆盖错误的 _.map 函数

或者就像我用它作为一个mixin

_.mapobj ( options , function( val, key, list ) 
于 2014-10-11T06:27:32.363 回答
0

您可以_.mapValues(users, function(o) { return o.age; });在 Lodash 和 Underscore中使用_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

在此处查看交叉文档:http: //jonathanpchen.com/underdash-api/#mapvalues-object-iteratee-identity

于 2016-12-31T01:44:02.210 回答
0

_.map 使用 lodash 之类的循环来实现这一点

 var result={};
_.map({one: 1, two: 2, three: 3}, function(num, key){ result[key]=num * 3; });
console.log(result)

//output
{one: 1, two: 2, three: 3}

Reduce 很聪明,看起来像上面的 answare

_.reduce({one: 1, two: 2, three: 3}, function(result, num, key) {
  result[key]=num * 3
  return result;
}, {});

//output
{one: 1, two: 2, three: 3}
于 2020-10-08T14:09:38.317 回答