对象的映射函数(而不是数组)

时间:2013-02-11 10:41:13

标签: javascript node.js functional-programming map-function

我有一个对象:

myObject = { 'a': 1, 'b': 2, 'c': 3 }

我正在寻找一种类似于Array.prototype.map的本机方法,其使用方法如下:

newObject = myObject.map(function (value, label) {
    return value * value;
});

// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

JavaScript是否对对象有这样的map函数? (我想将它用于Node.JS,所以我不关心跨浏览器问题。)

43 个答案:

答案 0 :(得分:1122)

map对象没有原生Object,但是这个怎么样:

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

Object.keys(myObject).map(function(key, index) {
  myObject[key] *= 2;
});

console.log(myObject);
// => { 'a': 2, 'b': 4, 'c': 6 }

但您可以使用for ... in轻松迭代对象:

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

for (var key in myObject) {
  if (myObject.hasOwnProperty(key)) {
    myObject[key] *= 2;
  }
}

console.log(myObject);
// { 'a': 2, 'b': 4, 'c': 6 }

<强>更新

很多人都提到以前的方法不返回新对象,而是操作对象本身。就此而言,我想添加另一个返回新对象的解决方案,并保留原始对象:

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

// returns a new object with the values at each key mapped using mapFn(value)
function objectMap(object, mapFn) {
  return Object.keys(object).reduce(function(result, key) {
    result[key] = mapFn(object[key])
    return result
  }, {})
}

var newObject = objectMap(myObject, function(value) {
  return value * 2
})

console.log(newObject);
// => { 'a': 1, 'b': 4, 'c': 6 }

console.log(myObject);
// => { 'a': 1, 'b': 2, 'c': 3 }

Array.prototype.reduce通过稍微合并先前的值和当前值将数组减少为单个值。该链由空对象{}初始化。在每次迭代中,添加myObject的新键,其方块为值。

答案 1 :(得分:210)

如何在普通JS( ES6 / ES2015 )中使用即时变量赋值的单行程怎么样?

利用spread operatorcomputed key name语法:

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

jsbin

使用reduce的另一个版本:

let newObj = Object.keys(obj).reduce((p, c) => ({...p, [c]: obj[c] * obj[c]}), {});

jsbin

作为函数的第一个例子:

const oMap = (o, f) => Object.assign({}, ...Object.keys(o).map(k => ({ [k]: f(o[k]) })));

// To square each value you can call it like this:
let mappedObj = oMap(myObj, (x) => x * x);

jsbin

如果要以功能样式映射嵌套对象递归,可以这样做:

const sqrObjRecursive = (obj) => 
  Object.keys(obj).reduce((newObj, key) => 
    (obj[key] && typeof obj[key] === 'object') ?
      {...newObj, [key]: sqrObjRecursive(obj[key])} :  // recurse.
      {...newObj, [key]: obj[key] * obj[key]}          // square val.
    ,{})       

jsbin

或更重要的是,像这样:

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

jsbin

ES7 / ES2016 以来,您可以使用Object.entries代替Object.keys,例如像这样:

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


继承属性和原型链:

在极少数情况下,您可能需要映射一个类类对象,该对象在其prototype-chain上包含继承对象的属性。在这种情况下Object.keys()无法正常工作,因为Object.keys()不会枚举继承的属性。如果您需要映射继承的属性,则应使用for (key in myObj) {...}

以下是一个继承另一个对象属性的对象示例,以及Object.keys()在这种情况下的工作方式。

const obj1 = { 'a': 1, 'b': 2, 'c': 3}
const obj2 = Object.create(obj1);  // One of multiple ways to inherit an object in JS.

// Here you see how the properties of obj1 sit on the 'prototype' of obj2
console.log(obj2)  // Prints: obj2.__proto__ = { 'a': 1, 'b': 2, 'c': 3}

console.log(Object.keys(obj2));  // Prints: an empty Array.

for (key in obj2) {
  console.log(key);              // Prints: 'a', 'b', 'c'
}

jsbin

但是,请帮我一个忙,避免继承。 : - )

答案 2 :(得分:98)

没有原生方法,但lodash#mapValues能很好地完成工作

_.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
// → { 'a': 3, 'b': 6, 'c': 9 }

答案 3 :(得分:55)

写一个很容易:

Object.map = function(o, f, ctx) {
    ctx = ctx || this;
    var result = {};
    Object.keys(o).forEach(function(k) {
        result[k] = f.call(ctx, o[k], k, o); 
    });
    return result;
}

示例代码:

> o = { a: 1, b: 2, c: 3 };
> r = Object.map(o, function(v, k, o) {
     return v * v;
  });
> r
{ a : 1, b: 4, c: 9 }

注意:此版本还允许您(可选)为回调设置this上下文,就像Array方法一样。

编辑 - 已更改为删除Object.prototype的使用,以确保它不会与对象上名为map的任何现有属性冲突。

答案 4 :(得分:22)

您可以在返回的键数组上使用Object.keys然后forEach

var myObject = { 'a': 1, 'b': 2, 'c': 3 },
    newObject = {};
Object.keys(myObject).forEach(function (key) {
    var value = myObject[key];
    newObject[key] = value * value;
});

或者采用更模块化的方式:

function map(obj, callback) {
    var result = {};
    Object.keys(obj).forEach(function (key) {
        result[key] = callback.call(obj, obj[key], key, obj);
    });
    return result;
}

newObject = map(myObject, function(x) { return x * x; });

请注意,Object.keys返回一个仅包含对象自己的可枚举属性的数组,因此它的行为类似于for..in循环并且hasOwnProperty检查。

答案 5 :(得分:16)

这是直接的bs,JS社区中的每个人都知道它。 应该是这个功能:

const obj1 = {a:4, b:7};
const obj2 = Object.map(obj1, (k,v) => v + 5);

console.log(obj1); // {a:4, b:7}
console.log(obj2); // {a:9, b:12}

这是天真的实施:

Object.map = function(obj, fn, ctx){

    const ret = {};

    for(let k of Object.keys(obj)){
        ret[k] = fn.call(ctx || null, k, obj[k]);
    });

    return ret;
};

必须始终自己实施这一点非常烦人;)

如果你想要一些更复杂的东西,这不会干扰Object类,试试这个:

let map = function (obj, fn, ctx) {
  return Object.keys(obj).reduce((a, b) => {
    a[b] = fn.call(ctx || null, b, obj[b]);
    return a;
  }, {});
};


const x = map({a: 2, b: 4}, (k,v) => {
    return v*2;
});

但是将这个map函数添加到Object是安全的,只是不要添加到Object.prototype。

Object.map = ... // fairly safe
Object.prototype.map ... // not ok

答案 6 :(得分:15)

我来到这里寻找并回答将对象映射到数组并获得此页面的结果。如果你来到这里寻找我的答案,这里是你如何映射和对象的数组。

您可以使用map从对象返回一个新数组,如下所示:

var newObject = Object.keys(myObject).map(function(key) {
   return myObject[key];
});

答案 7 :(得分:10)

接受的答案有两个缺点:

  • 它误用Array.prototype.reduce,因为减少意味着改变复合类型的结构,在这种情况下不会发生。
  • 不是特别可重复使用

ES6 / ES2015功能方法

请注意,所有功能都以咖喱形式定义。

// small, reusable auxiliary functions

const keys = o => Object.keys(o);

const assign = (...o) => Object.assign({}, ...o);

const map = f => xs => xs.map(x => f(x));

const mul = y => x => x * y;

const sqr = x => mul(x) (x);


// the actual map function

const omap = f => o => {
  o = assign(o); // A
  map(x => o[x] = f(o[x])) (keys(o)); // B
  return o;
};


// mock data

const o = {"a":1, "b":2, "c":3};


// and run

console.log(omap(sqr) (o));
console.log(omap(mul(10)) (o));

  • 在行A o被重新分配。由于Javascript传递了引用值by sharing,因此会生成o的浅表副本。我们现在能够在o内变异omap,而不会在父范围内改变o
  • 在行B中map的返回值被忽略,因为map执行o的变异。由于此副作用仍在omap范围内且在父范围内不可见,因此完全可以接受。

这不是最快的解决方案,而是一个声明性和可重用的解决方案。这是与单行,简洁但不太可读的相同的实现:

const omap = f => o => (o = assign(o), map(x => o[x] = f(o[x])) (keys(o)), o);

附录 - 为什么默认情况下对象不可迭代?

ES2015指定了迭代器和可迭代协议。但是对象仍然不可迭代,因此无法映射。 The reason is the mixing of data and program level

答案 8 :(得分:8)

为了获得最佳性能。

如果您的对象不经常更改但需要经常迭代,我建议使用本机Map作为缓存。

&#13;
&#13;
// example object
var obj = {a: 1, b: 2, c: 'something'};

// caching map
var objMap = new Map(Object.entries(obj));

// fast iteration on Map object
objMap.forEach((item, key) => {
  // do something with an item
  console.log(key, item);
});
&#13;
&#13;
&#13;

Object.entries已经可以在Chrome,Edge,Firefox和Beta Opera中使用,因此它具有面向未来的功能。 它来自ES7,因此对于IE来说它是https://github.com/es-shims/Object.entries,它不起作用。

答案 9 :(得分:7)

最小版本(es6):

Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})

答案 10 :(得分:5)

您可以在数组上使用map方法和forEach方法,但是如果您想在Object上使用它,则可以像下面这样扭曲使用它:

使用Javascript(ES6)

var obj = { 'a': 2, 'b': 4, 'c': 6 };   
Object.entries(obj).map( v => obj[v[0]] *= v[1] );
console.log(obj); //it will log as {a: 4, b: 16, c: 36}

var obj2 = { 'a': 4, 'b': 8, 'c': 10 };
Object.entries(obj2).forEach( v => obj2[v[0]] *= v[1] );
console.log(obj2); //it will log as {a: 16, b: 64, c: 100}

使用jQuery

var ob = { 'a': 2, 'b': 4, 'c': 6 };
$.map(ob, function (val, key) {
   ob[key] *= val;
});
console.log(ob) //it will log as {a: 4, b: 16, c: 36}

或者您也可以使用其他循环,例如$.each方法,如下例:

$.each(ob,function (key, value) {
  ob[key] *= value;
});
console.log(ob) //it will also log as {a: 4, b: 16, c: 36}

答案 11 :(得分:4)

这个答案已被重写,以展示一个强大的组合者mapReduce,它允许我们以不同的方式思考我们的转变

  1. m映射函数 - 让您有机会在...之前转换传入元素。
  2. r reduce 函数 - 此函数将累加器与映射元素的结果相结合
  3. 直观地,mapReduce创建了一个新的reducer,我们可以直接插入Array.prototype.reduce。但更重要的是,我们可以通过利用对象monoid omapObject.assign来实现我们的对象仿函数实现{}

    const identity = x =>
      x
      
    const first = (a, b) =>
      a
      
    const mapReduce = (m = identity, r = first) =>
      (acc, x) => r (acc, m (x))
      
    const omap = (o = {}, f = identity) =>
      Object.keys (o)
        .reduce ( mapReduce ( k => ({ [k]: f (o [k]) })  // Object.map
                            , Object.assign              // Object.concat
                            )
                , {}                                     // Object.empty
                )
              
    const square = x =>
      x * x
      
    const data =
      { a : 1, b : 2, c : 3 }
      
    console.log (omap (data, square))
    // { a : 1, b : 4, c : 9 }

    请注意,我们实际需要编写的程序的唯一部分是映射实现本身 -

    k => ({ [k]: f (o [k]) }
    

    在给定已知对象o和某个键k的情况下,构造一个对象,其属性k是对键值调用f的结果, o [k]

    如果我们首先抽象mapReduce

    ,我们可以看到oreduce的测序潜力
    const oreduce = (o, f = first, acc = {}) =>
      Object.keys (o)
        .reduce ( mapReduce ( k => [ k, o[k] ]
                            , f
                            )
                , acc
                )
    
    const omap = (o = {}, f = identity) =>
      oreduce ( o
              , mapReduce ( ([ k, v ]) => ({ [k]: f (v) })
                          , Object.assign
                          )
              , {}
              )
    

    一切都是一样的,但现在可以在更高级别定义omap。当然新Object.entries使这看起来很傻,但练习对学习者来说仍然很重要。

    你不会在这里看到mapReduce的全部潜力,但我同意这个答案,因为看到它可以应用多少个地方很有意思。如果您对其衍生方式以及其他有用的方式感兴趣,请参阅this answer

答案 12 :(得分:3)

JavaScript刚获得了新的Object.fromEntries方法。

示例

const myObject = { a: 1, b: 2, c: 3 }
const myNewObject = Object.fromEntries(
  Object
    .entries(myObject)
    .map(([key, value]) => ([key, value * value]))
)
console.log(myNewObject)

说明

上面的代码将Object转换为可映射的嵌套数组([[<key>,<value>], ...])。 Object.fromEntries将数组转换回对象。

此模式的妙处在于,您现在可以轻松地在映射时考虑对象键。

文档

浏览器支持

Object.fromEntries当前仅受these browsers/engines支持,尽管有可用的polyfill(例如@babel/polyfill)。

答案 13 :(得分:3)

map function上不存在Object.prototype,但你可以像这样模仿它

var myMap = function ( obj, callback ) {

    var result = {};

    for ( var key in obj ) {
        if ( Object.prototype.hasOwnProperty.call( obj, key ) ) {
            if ( typeof callback === 'function' ) {
                result[ key ] = callback.call( obj, obj[ key ], key, obj );
            }
        }
    }

    return result;

};

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

var newObject = myMap( myObject, function ( value, key ) {
    return value * value;
});

答案 14 :(得分:2)

您只需使用以下命令即可将对象转换为数组:

您可以将对象值转换为数组:

myObject = { 'a': 1, 'b': 2, 'c': 3 };

let valuesArray = Object.values(myObject);

console.log(valuesArray);

您可以将对象键转换为数组:

myObject = { 'a': 1, 'b': 2, 'c': 3 };

let keysArray = Object.keys(myObject);

console.log(keysArray);

现在您可以执行常规的数组操作,包括“地图”功能

答案 15 :(得分:2)

基于@Amberlamps答案,这是一个效用函数 (作为评论看起来很难看)

function mapObject(obj, mapFunc){
    return Object.keys(obj).reduce(function(newObj, value) {
        newObj[value] = mapFunc(obj[value]);
        return newObj;
    }, {});
}

,用途是:

var obj = {a:1, b:3, c:5}
function double(x){return x * 2}

var newObj = mapObject(obj, double);
//=>  {a: 2, b: 6, c: 10}

答案 16 :(得分:2)

var myObject = { 'a': 1, 'b': 2, 'c': 3 };


Object.prototype.map = function(fn){
    var oReturn = {};
    for (sCurObjectPropertyName in this) {
        oReturn[sCurObjectPropertyName] = fn(this[sCurObjectPropertyName], sCurObjectPropertyName);
    }
    return oReturn;
}
Object.defineProperty(Object.prototype,'map',{enumerable:false});





newObject = myObject.map(function (value, label) {
    return value * value;
});


// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

答案 17 :(得分:2)

如果您对map ping不仅仅是值而且还感兴趣,那么我写了Object.map(valueMapper, keyMapper),其行为方式如下:

var source = { a: 1, b: 2 };
function sum(x) { return x + x }

source.map(sum);            // returns { a: 2, b: 4 }
source.map(undefined, sum); // returns { aa: 1, bb: 2 }
source.map(sum, sum);       // returns { aa: 2, bb: 4 }

答案 18 :(得分:2)

我认为这是谷歌搜索中的第一项,试图学习如何做到这一点,并认为我会分享给其他folsk最近发现我找到的解决方案,它使用npm包不可变。

我认为分享它很有意思,因为不可变在他们自己的文档中使用OP的精确情况 - 以下不是我自己的代码,而是从当前的immutable-js文档中提取:

const { Seq } = require('immutable')
const myObject = { a: 1, b: 2, c: 3 }
Seq(myObject).map(x => x * x).toObject();
// { a: 1, b: 4, c: 9 } 

Seq没有其他属性(&#34; Seq描述了一个惰性操作,允许它们通过不创建中间集合来有效地链接所有高阶集合方法(例如map和filter)#34;)并且其他一些不可变的js数据结构也可以非常有效地完成这项工作。

使用此方法的任何人当然都必须npm install immutable并且可能想要阅读文档:

https://facebook.github.io/immutable-js/

答案 19 :(得分:1)

定义函数mapEntries。

mapEntries带有一个回调函数,该函数在对象中的每个条目上使用参数值,键和对象进行调用。它应该返回一个新值。

mapEntries应该返回一个新对象,并带有从回调中返回的新值。

Object.defineProperty(Object.prototype, 'mapEntries', {
  enumerable: false,
  value: function (mapEntriesCallback) {
    return Object.fromEntries(
      Object.entries(this).map(
        ([key, value]) => [key, mapEntriesCallback(value, key, this)]
      )
    )
  }
})


// Usage example:

var object = {a: 1, b: 2, c: 3}
var newObject = object.mapEntries(value => value * value)
console.log(newObject)
//> {a: 1, b: 4, c: 9}

编辑: 以前的版本没有指定这不是可枚举的属性

答案 20 :(得分:1)

我的回复很大程度上基于此处的最高评分,希望大家都能理解(我的GitHub上也有相同的解释)。这就是为什么他对地图的重视:

Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +    
')');

该函数的目的是使用一个对象并使用所有对象(对象和数组之类)可用的方法修改该对象的原始内容,而不返回数组。 JS中的几乎所有东西都是一个对象,因此,在继承流程中更远的元素可以在技术上潜在地使用那些对继承人可用的元素(和出现的情况相反)。

之所以可行,是因为.map函数返回一个数组,要求您提供数组的显式或隐式RETURN,而不是简单地修改现有对象。实际上,您可以使用Object.keys欺骗程序,使该对象认为该对象是数组。这将允许您使用map函数及其对各个键所关联的值的作用(我实际上不小心返回了数组,但已将其修复)。只要没有正常意义上的回报,就不会创建原始对象stil完好无损并按程序进行修改的数组。

此特定程序接受一个称为图像的对象,并获取其键的值,并附加url标记以在另一个函数中使用。原来是这个:

var images = { 
snow: 'https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305', 
sunny: 'http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-east-   
Matanzas-city- Cuba-20170131-1080.jpg', 
rain: 'https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg' };

...修改为:

var images = { 
snow: url('https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305'),     
sunny: url('http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-   
east-Matanzas-city- Cuba-20170131-1080.jpg'), 
rain: url('https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg') 
};

只要没有返回值,对象的原始结构就保持不变,允许进行常规属性访问。不要让它像正常一样返回数组,一切都会好起来的。目标是将原始值(images [key])重新分配给所需的内容,而不是其他任何内容。据我所知,为了防止数组输出,必须重新分配images [key],并且没有隐式或显式的返回数组的请求(可变赋值会这样做,并且对我来回切换)。

编辑:

要解决有关创建新对象的另一种方法,以避免修改原始对象(并且似乎仍然有必要进行重新分配,以避免意外地将数组创建为输出)。这些函数使用箭头语法,如果您只是想创建一个新对象以备将来使用,则是这些。

const mapper = (obj, mapFn) => Object.keys(obj).reduce((result, key) => {
                result[key] = mapFn(obj)[key];
                return result;
            }, {});

var newImages = mapper(images, (value) => value);

这些功能的工作方式如下:

mapFn使用稍后要添加的函数(在这种情况下为(值)=> value),并简单地返回存储在该处的任何内容作为该键的值(如果像他一样更改返回值,则乘以2)。在mapFn(obj)[key]中,

,然后在result [key] = mapFn(obj)[key]

中重新定义与该键关联的原始值

并返回对结果执行的操作(累加器位于.reduce函数末尾的方括号中)。

所有这些操作都是在所选对象上执行的,仍然无法对返回的数组进行隐式请求,并且仅在重新分配值时才起作用。如上所示,这需要进行一些心理体操,但会减少所需的代码行。输出与下面完全相同:

{snow: "https://www.trbimg.com/img-5aa059f5/turbine/bs-   
md-weather-20180305", sunny: "http://www.cubaweather.org/images/weather-
photos/l…morning-east-Matanzas-city-Cuba-20170131-1080.jpg", rain: 
"https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg"}

请记住,这适用于NON-NUMBERS。您可以通过简单地返回mapFN函数中的值来复制任何对象。

答案 21 :(得分:1)

First, convert your HTMLCollection using Object.entries(collection). Then it’s an iterable you can now use the .map method on it.

Object.entries(collection).map(...)

reference https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31

答案 22 :(得分:1)

要更精确地响应OP要求的 ,OP需要一个对象:

  

myObject = { 'a': 1, 'b': 2, 'c': 3 }

具有映射方法myObject.map

  

类似于Array.prototype.map,其用法如下:

newObject = myObject.map(function (value, label) {
    return value * value;
});
// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

最好的 imho (根据“ 接近所要求的内容” +“不需要不必要的ES {5,6,7}”来衡量)答案是:

myObject.map = function mapForObject(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property) && property != "map"){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

上面的代码避免了有意使用任何语言功能的情况,只有在最新的ECMAScript版本中才可用。使用上面的代码可以解决此问题:

myObject = { 'a': 1, 'b': 2, 'c': 3 };

myObject.map = function mapForObject(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property) && property != "map"){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

newObject = myObject.map(function (value, label) {
  return value * value;
});
console.log("newObject is now",newObject);
alternative test code here

除了一些人不愿接受的解决方案外,还可以将解决方案插入这样的原型链中。

Object.prototype.map = function(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property)){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

某些东西,经过仔细的监督,应该不会有任何不良影响,也不会影响其他对象的map方法(即Array的map)。

答案 23 :(得分:1)

您可以通过有序对使用简单的for-in循环。我使用了<!-- Fixed navbar --> <nav id="home" class="navbar navbar-custom navbar-fixed-top" role="navigation"> <div> <div class="navbar-header page-scroll"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse"> <i class="fa fa-bars"></i> </button> <a class="navbar-brand" href="index.html"> <img class="img-responsive" alt="logo" src="img/logo.png"> </a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-right navbar-main-collapse hmodal"> <ul class="nav navbar-nav" style="padding-right:15px;"> <li><button class="ui inverted compact small yellow button" style="margin-top:8px; ">Become a Partner</button></li> <li class="active"><a href="#">Track</a></li> <li><a href="tel:+917878000666" rel="nofollow"><i class="fa fa-phone"></i>Call +91 7878 000 666</a></li> <li><a href="#notification"><i class="fa fa-bell" aria-hidden="true"></i></a></li> <li><a class="cd-signin" href="#Login">Login/Signup</a></li> <li><a href="#"><i class="fa fa-map-marker" aria-hidden="true"></i> Location</a> <div class="dialog" style="display:none"> <div class="title">Add Event</div> <form action="#" method="post"> <input type="submit" value="Ok"/> </form></li> </ul> </div> <!-- /.navbar-collapse --> </div> <!-- /.container --> </nav>,因为您为对象创建了三个属性(带有值)。第一种方法不会创建地图。相反,它只是将函数应用于单个元素,这可以在很多情况下大大加快执行速度。

第二种方法以与第一种方法类似的方式创建地图,但可能比其他答案慢得多。

hasOwnProperty()
var myObject = { 'a': 1, 'b': 2, 'c': 3 }

//Doesn't create a map, just applies the function to a specific element
function getValue(key) {
  for (var k in myObject) {
    if (myObject.hasOwnProperty(key)) {
      var value = myObject[key]
      return value * value; //stops iteration
    }
  }
}

//creates a map (answers question, but above function is better in some situations)
var newObject = {};
makeMap();

function makeMap() {
    for (var k in myObject) {
        var value = myObject[k];
        newObject[k] = value * value;
    }
}

console.log(newObject); //mapped array

答案 24 :(得分:1)

我特别想使用我用于单个对象的数组的相同功能,并希望保持简单。这对我有用:

var mapped = [item].map(myMapFunction).pop();

答案 25 :(得分:1)

我需要一个允许修改键的版本(基于@Amberlamps和@yonatanmn答案);

@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
    CommandResult result = this.mongoTemplate.executeCommand("{ buildInfo: 1 }");
    builder.up().withDetail("version", result.getString("version"));
}

factObject =

var facts = [ // can be an object or array - see jsfiddle below
    {uuid:"asdfasdf",color:"red"},
    {uuid:"sdfgsdfg",color:"green"},
    {uuid:"dfghdfgh",color:"blue"}
];

var factObject = mapObject({}, facts, function(key, item) {
    return [item.uuid, {test:item.color, oldKey:key}];
});

function mapObject(empty, obj, mapFunc){
    return Object.keys(obj).reduce(function(newObj, key) {
        var kvPair = mapFunc(key, obj[key]);
        newObj[kvPair[0]] = kvPair[1];
        return newObj;
    }, empty);
}

编辑:稍微更改以传入起始对象{}。允许它为[](如果键是整数)

答案 26 :(得分:1)

嘿写了一个可能有帮助的小映射器功能。

    function propertyMapper(object, src){
         for (var property in object) {   
           for (var sourceProp in src) {
               if(property === sourceProp){
                 if(Object.prototype.toString.call( property ) === '[object Array]'){
                   propertyMapper(object[property], src[sourceProp]);
                   }else{
                   object[property] = src[sourceProp];
                }
              }
            }
         }
      }

答案 27 :(得分:0)

我需要一个函数来选择性地映射不仅(也不是唯一的)值,而且还映射键。原始对象不应更改。该对象也仅包含原始值。

function mappedObject(obj, keyMapper, valueMapper) {

    const mapped = {};
    const keys   = Object.keys(obj);
    const mapKey = typeof keyMapper == 'function';
    const mapVal = typeof valueMapper == 'function';

    for (let i = 0; i < keys.length; i++) {
        const key = mapKey ? keyMapper(keys[i]) : keys[i];
        const val = mapVal ? valueMapper(obj[keys[i]]) : obj[keys[i]];
        mapped[key] = val;
    }

    return mapped;
}

使用。传递一个 keymapper 和一个 valuemapper 函数:

const o1 = { x: 1, c: 2 }
mappedObject(o1, k => k + '0', v => v + 1) // {x0: 2, c0: 3}

答案 28 :(得分:0)

这是另一个版本,它允许映射(减少)函数基于当前键和值声明任意数量的新属性(键和值)。 E:现在也适用于数组。

Object.defineProperty(Object.prototype, 'reduceEntries', {
  value: function(f,a=Array.isArray(this)?[]:{}) {
    return Object.entries(this).reduce( (o, [k,v]) => 
      Object.assign(o, f(v, Array.isArray(a)?Number(k):k, this)),
      a);
  }
});

const data = { a : 1, b : 2, c : 3 };
const calculate = (v, k) => ({
  [k+'_square']: v*v,
  [k+'_cube']: v*v*v
});
console.log( data.reduceEntries( calculate ) );
// {
//  "a_square": 1,  "a_cube": 1,
//  "b_square": 4,  "b_cube": 8,
//  "c_square": 9,  "c_cube": 27
// }

// Demonstration with an array:
const arr = [ 'a', 'b', 'c' ];
const duplicate = (v, i) => ({
  [i*2]: v,
  [i*2+1]: v+v
});
console.log( arr.reduceEntries( duplicate ) );
// [ "a", "aa", "b", "bb", "c", "cc" ]

答案 29 :(得分:0)

异步,有人吗?

尽管有大量评论,但我没有找到使用 async 映射器的解决方案。这是我的。

使用 p-map,一个受信任的 (@sindresorhus) 和小的依赖项。

打字稿:

import pMap from "p-map";

export const objectMapAsync = async <InputType, ResultType>(
  object: { [s: string]: InputType } | ArrayLike<InputType>,
  mapper: (input: InputType, key: string, index: number) => Promise<ResultType>
): Promise<{
  [k: string]: ResultType;
}> => {
  const mappedTuples = await pMap(
    Object.entries(object),
    async ([key, value], index) => {
      const result = await mapper(value, key, index);
      return [key, result];
    }
  );

  return Object.fromEntries(mappedTuples);
};

普通JS:

import pMap from "p-map";

export const objectMapAsync = async (
  object,
  mapper
) => {
  const mappedTuples = await pMap(
    Object.entries(object),
    async ([key, value], index) => {
      const result = await mapper(value, key, index);
      return [key, result];
    }
  );

  return Object.fromEntries(mappedTuples);
};

};

答案 30 :(得分:0)

2020更新,覆盖Object.prototype

Object.prototype.map = function(func){
    for(const [k, v] of Object.entries(this)){
        func(k, v);
    }
    return this;
}

Object.prototype.reject = function(func){
    for(const [k, v] of Object.entries(this)){
        if(func(k, v)){
            delete this[k];
        }
    }
    return this;
}

Object.prototype.filter = function(func){
    let res = {};
    for(const [k, v] of Object.entries(this)){
        if(!func(k, v)){
            delete this[k];
        }
    }
    return this;
}

a = {
    1: ['a', '1'],
    2: ['b', '2'],
    3: ['a', '3'],
};

console.log(Object.assign({}, a).map((k, v) => v.push('nice')));
// {
//   '1': [ 'a', '1', 'nice' ],
//   '2': [ 'b', '2', 'nice' ],
//   '3': [ 'a', '3', 'nice' ]
// }

console.log(Object.assign({}, a).reject((k, v)=>v[0] === 'a'));
// { '2': [ 'b', '2', 'nice' ] }

console.log(Object.assign({}, a).filter((k, v)=>v[0] === 'a'));
// { '1': [ 'a', '1', 'nice' ], '3': [ 'a', '3', 'nice' ] }

答案 31 :(得分:0)

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

for (var key in myObject) {
  if (myObject.hasOwnProperty(key)) {
    myObject[key] *= 2;
  }
}

console.log(myObject);
// { 'a': 2, 'b': 4, 'c': 6 }

答案 32 :(得分:0)

var myObject = { 'a': 1, 'b': 2, 'c': 3 };
Object.keys(myObject).filter((item) => myObject[item] *= 2)
console.log(myObject)

答案 33 :(得分:0)

const mapObject = (targetObject, callbackFn) => {
    if (!targetObject) return targetObject;
    if (Array.isArray(targetObject)){
        return targetObject.map((v)=>mapObject(v, callbackFn))
    }
    return Object.entries(targetObject).reduce((acc,[key, value]) => {
        const res = callbackFn(key, value);
        if (!Array.isArray(res) && typeof res ==='object'){
            return {...acc, [key]: mapObject(res, callbackFn)}
        }
        if (Array.isArray(res)){
            return {...acc, [key]: res.map((v)=>mapObject(v, callbackFn))}
        }
        return {...acc, [key]: res};
    },{})
};
const mapped = mapObject(a,(key,value)=> {
    if (!Array.isArray(value) && key === 'a') return ;
    if (!Array.isArray(value) && key === 'e') return [];
    if (!Array.isArray(value) && key === 'g') return value * value;
    return value;
});
console.log(JSON.stringify(mapped)); 
// {"b":2,"c":[{"d":2,"e":[],"f":[{"g":4}]}]}

此函数递归遍历对象和对象数组。如果返回未定义的属性,则可以删除

答案 34 :(得分:0)

TypeScript中的对象映射器

我喜欢使用Object.fromEntries的示例,例如this one,但仍然不是很容易使用。使用Object.keys然后查找key的答案实际上是在进行多次查找,而这些查找可能不是必需的。

我希望有一个Object.map函数,但是我们可以创建自己的函数并将其命名为objectMap,并且可以同时修改keyvalue

用法(JavaScript):

const myObject = { 'a': 1, 'b': 2, 'c': 3 };

// keep the key and modify the value
let obj = objectMap(myObject, val => val * 2);
// obj = { a: 2, b: 4, c: 6 }


// modify both key and value
obj = objectMap(myObject,
    val => val * 2 + '',
    key => (key + key).toUpperCase());
// obj = { AA: '2', BB: '4', CC: '6' }

代码(TypeScript):

interface Dictionary<T> {
    [key: string]: T;
}

function objectMap<TValue, TResult>(
    obj: Dictionary<TValue>,
    valSelector: (val: TValue, obj: Dictionary<TValue>) => TResult,
    keySelector?: (key: string, obj: Dictionary<TValue>) => string,
    ctx?: Dictionary<TValue>
) {
    const ret = {} as Dictionary<TResult>;
    for (const key of Object.keys(obj)) {
        const retKey = keySelector
            ? keySelector.call(ctx || null, key, obj)
            : key;
        const retVal = valSelector.call(ctx || null, obj[key], obj);
        ret[retKey] = retVal;
    }
    return ret;
}

如果您不使用TypeScript,则将上面的代码复制到TypeScript Playground中以获取JavaScript代码。

此外,我将keySelector放在参数列表中valSelector之后的原因是因为它是可选的。

*亚历山大·米尔斯的answer功不可没。

答案 35 :(得分:0)

我只处理字符串以减少豁免:

Object.keys(params).map(k => typeof params[k] == "string" ? params[k] = params[k].trim() : null);

答案 36 :(得分:0)

ES6:

Object.prototype.map = function(mapFunc) {
    return Object.keys(this).map((key, index) => mapFunc(key, this[key], index));
}

ES2015:

Object.prototype.map = function (mapFunc) {
    var _this = this;

    return Object.keys(this).map(function (key, index) {
        return mapFunc(key, _this[key], index);
    });
};

在节点中测试:

> a = {foo: "bar"}
{ foo: 'bar' }
> a.map((k,v,i) => v)
[ 'bar' ]

答案 37 :(得分:0)

settings = {
  message_notification: {
    value: true,
    is_active: true,
    slug: 'message_notification',
    title: 'Message Notification'
  },
  support_notification: {
    value: true,
    is_active: true,
    slug: 'support_notification',
    title: 'Support Notification'
  },
};

let keys = Object.keys(settings);
keys.map(key=> settings[key].value = false )
console.log(settings)

答案 38 :(得分:-1)

一个不同的选择是使用自定义json字符串化函数,该函数也可以在深层对象上工作。如果您打算将其以json的形式发布到服务器,这可能会很有用

const obj = { 'a': 1, 'b': 2, x: {'c': 3 }}
const json = JSON.stringify(obj, (k, v) => typeof v === 'number' ? v * v : v)

console.log(json)
console.log('back to json:', JSON.parse(json))

答案 39 :(得分:-1)

如果有人在寻找将对象映射到新对象或数组的简单解决方案:

// Maps an object to a new object by applying a function to each key+value pair.
// Takes the object to map and a function from (key, value) to mapped value.
const mapObject = (obj, fn) => {
    const newObj = {};
    Object.keys(obj).forEach(k => { newObj[k] = fn(k, obj[k]); });
    return newObj;
};

// Maps an object to a new array by applying a function to each key+value pair.
// Takes the object to map and a function from (key, value) to mapped value.
const mapObjectToArray = (obj, fn) => (
    Object.keys(obj).map(k => fn(k, obj[k]))
);

这可能不适用于所有对象或所有映射函数,但它适用于简单的浅层对象和简单的映射函数,这是我所需要的。

答案 40 :(得分:-1)

const orig = { 'a': 1, 'b': 2, 'c': 3 }

const result = _.transform(orig, (r, v, k) => r[k.trim()] = v * 2);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

使用新的 _.transform() to transforms object

答案 41 :(得分:-2)

TypeScript中的对象映射器

我喜欢使用final EditText edittext = (EditText) findViewById(R.id.edit); edittext.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (before == 0 && count == 1 && s.charAt(start) == '\n') { String text = edittext.getText().replace(start, start + 1, "").toString(); // Removes the enter Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show(); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); 的示例,例如this one,但仍然不是很容易使用。使用Imports System.ComponentModel Public Class Form1 Public BS As New BindingSource() Dim DtSet As New DataSet Private WithEvents N_Math As New MathList Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load With DtSet .Tables.Add("Math") With .Tables("Math") .Columns.Add("Param1", GetType(Double)) .Columns("Param1").DefaultValue = DBNull.Value .Columns.Add("Param2", GetType(Double)) .Columns("Param2").DefaultValue = DBNull.Value .Columns.Add("Result", GetType(Double)) .Columns("Result").DefaultValue = DBNull.Value End With End With BS.DataSource = DtSet.Tables("Math") DataGridView1.DataSource = BS '//Parameters tb_p1.DataBindings.Add("Text", Me.N_Math, "Param1") tb_p2.DataBindings.Add("Text", Me.N_Math, "Param2") '//Calculate result with the function tb_r.DataBindings.Add("Text", BS, "Result") End Sub Function Calculate_FN(ByVal p1 As Double, ByVal p2 As Double) As Double Dim res As Double res = p1 * p2 * 1000 Return res End Function Public Class MathList Implements INotifyPropertyChanged Public _Param1 As Double Public _Param2 As Double Public Property Param1() As Double Get Return _Param1 End Get Set(ByVal value As Double) If value <> _Param1 Then _Param1 = value NotifyPropertyChanged() End Set End Property Public Property Param2() As Double Get Return _Param2 End Get Set(ByVal value As Double) If value <> _Param2 Then _Param2 = value NotifyPropertyChanged() End Set End Property Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged Private Sub NotifyPropertyChanged() Form1.tb_r.Text = Form1.Calculate_FN(_Param1, _Param2) End Sub End Class Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim drv As DataRowView = DirectCast(BS.AddNew(), DataRowView) BS.EndEdit() End Sub 然后查找Object.fromEntries的答案实际上会进行多次查找,而这些查找可能不是必需的。

我同意@alexander-mills的观点,应该有一个静态的Object.keys函数。我在TypeScript中扩展了他的实现,并得到了这一点:

用法:

key

代码:

Object.map

如果您不想使用TypeScript(为什么?),则将上面的代码复制到TypeScript Playground中以获取JavaScript代码。

我将const myObject = { 'a': 1, 'b': 2, 'c': 3 }; // keep the key and modify the value let obj = Object.map(myObject, val => val * 2); // obj = { a: 2, b: 4, c: 6 } // modify both key and value obj = Object.map(myObject, val => val * 2 + '', key => (key + key).toUpperCase()); // obj = { AA: '2', BB: '4', CC: '6' } 放在第二位的原因是因为它是可选的。

此外,由于这不会修改interface Dictionary<T> { [key: string]: T; } interface ObjectConstructor { map<TValue, TResult>( obj: Dictionary<TValue>, valSelector: (val: TValue, obj: Dictionary<TValue>) => TResult, keySelector?: (key: string, obj: Dictionary<TValue>) => string, ctx?: Dictionary<TValue> ): Dictionary<TResult>; } function objectMap<TValue, TResult>( obj: Dictionary<TValue>, valSelector: (val: TValue, obj: Dictionary<TValue>) => TResult, keySelector?: (key: string, obj: Dictionary<TValue>) => string, ctx?: Dictionary<TValue> ) { const ret = {} as Dictionary<TResult>; for (const key of Object.keys(obj)) { const retKey = keySelector ? keySelector.call(ctx || null, key, obj) : key; const retVal = valSelector.call(ctx || null, obj[key], obj); ret[retKey] = retVal; } return ret; } Object.map = objectMap; 原型,因此我认为这是安全的,但是如果您不想触摸keySelector界面,则可以删除最后一行并使用{ {1}}。

答案 42 :(得分:-2)

使用以下映射函数定义myObject.map

o => f=> Object.keys(o).reduce((a,c)=> c=='map' ? a : (a[c]=f(o[c],c),a), {})

let map = o => f=> Object.keys(o).reduce((a,c)=> c=='map' ? a : (a[c]=f(o[c],c),a), {})



// TEST init

myObject = { 'a': 1, 'b': 2, 'c': 3 }
myObject.map = map(myObject);        

// you can do this instead above line but it is not recommended 
// ( you will see `map` key any/all objects)
// Object.prototype.map = map(myObject);

// OP desired interface described in question
newObject = myObject.map(function (value, label) {
    return  value * value;
});

console.log(newObject);