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

Javascript 对象的映射函数(而不是数组),javascript,node.js,functional-programming,map-function,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 } newObject = myObject.map(fun

我有一个目标:

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 }
newObject = myObject.map(function (value, label) { return value * value; }); // newObject is now { 'a': 1, 'b': 4, 'c': 9 }
JavaScript是否有这样的对象映射功能?(我希望Node.JS使用此功能,因此我不关心跨浏览器问题。)

对象上不存在
映射函数

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;
});

写一个很容易:

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
方法一样


编辑-更改为删除对
对象的使用。原型
,以确保它不会与对象上名为
映射
的任何现有属性冲突。

对象
对象没有本机的
映射
,但如何处理:

var myObject={'a':1,'b':2,'c':3};
Object.keys(myObject).map(函数(键,索引){
myObject[key]*=2;
});
console.log(myObject);
//=>{a':2,'b':4,'c':6}
您可以使用,然后在返回的键数组上使用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
返回一个仅包含对象自身可枚举属性的数组,因此它的行为类似于带有
hasOwnProperty
检查的
for.
循环中的..。

没有本机方法,但将出色地完成这项工作

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

如果您对
map
ping感兴趣,我已经写过,它的行为如下:

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 }

我来这里是想找到并回答将一个对象映射到一个数组的问题,结果得到了这个页面。如果您来这里寻找与我相同的答案,下面是如何将对象映射到数组

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

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

Hey编写了一个可能会有所帮助的小映射器函数

    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];
                }
              }
            }
         }
      }

基于@Amberlamps answer,这里有一个实用函数 (作为评论,它看起来很难看)

其用途是:

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}

公认的答案有两个缺点:


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

ES6/ES2015功能方法 请注意,所有函数都是以货币形式定义的

//小的、可重用的辅助函数
constkeys=o=>Object.keys(o);
常量赋值=(…o)=>Object.assign({},…o);
常量map=f=>xs=>xs.map(x=>f(x));
常数mul=y=>x=>x*y;
常数sqr=x=>mul(x)(x);
//实际映射函数
常数omap=f=>o=>{
o=赋值(o);//A
map(x=>o[x]=f(o[x])(键(o));//B
返回o;
};
//模拟数据
常数o={“a”:1,“b”:2,“c”:3};
//跑
控制台日志(omap(sqr)(o));

控制台日志(omap(mul(10))(o))JSES10/ES2019中的一行怎么样

利用和:

让newObj=Object.fromEntries(Object.entries(obj.map)([k,v])=>[k,v*v]);
作为函数编写的相同内容:

函数objMap(obj,func){
返回Object.fromEntries(Object.entries(obj.map)([k,v])=>[k,func(v)]);
}
//要将每个值平方,可以这样调用:
设mappedObj=objMap(obj,(x)=>x*x);
此函数还使用递归对嵌套对象进行平方运算:

函数objMap(obj,func){
返回Object.fromEntries(
Object.entries(obj.map)([k,v])=>
[k,v==Object(v)?objMap(v,func):func(v)]
)
);
}
//要将每个值平方,可以这样调用:
设mappedObj=objMap(obj,(x)=>x*x);
使用ES7/ES2016您不能使用
对象。fromEntries
,但您可以结合使用和语法实现相同的功能:

让newObj=Object.assign(…Object.entries(obj.map)([k,v])=>({[k]:v*v}));
ES6/ES2015不允许
Object.entries
,但您可以使用:

让newObj=Object.assign(…Object.keys(obj.map)(k=>({[k]:obj[k]*obj[k]}));
ES6还引入了循环,允许更具命令性的样式:

让newObj={}
for(让[k,v]为对象项(obj)){
newObj[k]=v*v;
}


array.reduce() 代替
Object.fromEntries
Object.assign
您还可以使用:

让newObj=Object.entries(obj).reduce((p[k,v])=>({…p[k]:v*v}),{});


继承的属性和原型链: 在某些罕见的情况下,您可能需要映射一个类类对象,该类对象在其上保存继承对象的属性。在这种情况下,
Object.keys()
Object.entries()
将不起作用,因为这些函数不包括原型链

如果需要映射继承的属性,可以使用
for(key in myObj){…}

以下是这种情况的一个例子:

const obj1={'a':1,'b':2,'c':3}
常量obj2=对象。创建(obj1);//在JS中继承对象的多种方法之一。
//在这里,您可以看到obj1的属性如何位于obj2的“原型”上
console.log(obj2)//Prints:obj2.\uuuuu proto\uuuuu={'a':1,'b':2,'c':3}
console.log(Object.keys(obj2));//打印:一个空数组。
console.log(Object.entries(obj2));//打印:一个空数组。
用于(让输入obj2){
console.log(key);//打印:“a”、“b”、“c”
}

不过,请帮我一个忙,避免继承。:-)

EDIT:使用较新JavaScript功能的标准方法是-

const identity = x =>
  x

const omap = (f = identity, o = {}) =>
  Object.fromEntries(
    Object.entries(o).map(([ k, v ]) =>
      [ k, f(v) ]
    )
  )
其中,
o
是某个对象,
f
是映射函数。或者我们可以说,给定一个来自
a->b
的函数和一个值为
a
类型的对象,生成一个值为
b
类型的对象。作为伪类型签名
// omap : (a -> b, { a }) -> { b }
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);
}
{
"asdfasdf": {"color":"red","oldKey":"0"},
"sdfgsdfg": {"color":"green","oldKey":"1"},
"dfghdfgh": {"color":"blue","oldKey":"2"}
}
var mapped = [item].map(myMapFunction).pop();
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;
};
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;
});
Object.map = ... // fairly safe
Object.prototype.map ... // not ok
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 }
Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})
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 } 
// 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]))
);
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}
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(ob,function (key, value) {
  ob[key] *= value;
});
console.log(ob) //it will also log as {a: 4, b: 16, c: 36}
newObject = myObject.map(function (value, label) { return value * value; }); // newObject is now { 'a': 1, 'b': 4, 'c': 9 }
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;
}
Object.entries(collection).map(...)
Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +    
')');
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') 
};
const mapper = (obj, mapFn) => Object.keys(obj).reduce((result, key) => {
                result[key] = mapFn(obj)[key];
                return result;
            }, {});

var newImages = mapper(images, (value) => value);
{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"}
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' }
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}]}]}