提问人:Randomblue 提问时间:2/11/2013 最后编辑:Will NessRandomblue 更新时间:9/27/2023 访问量:2689400
对象(而不是数组)的映射函数
map function for objects (instead of arrays)
问:
我有一个对象:
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 对对象有这样的函数吗?(我想要这个用于 Node.JS,所以我不关心跨浏览器问题。map
答:
上不存在,但是您可以像这样模拟它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;
});
评论
typeof callback === 'function'
map
callback
map
Object.prototype.hasOwnProperty.call( obj, key )
写一个很容易:
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
EDIT - 更改为删除 的使用,以确保它不会与对象上命名的任何现有属性冲突。Object.prototype
map
评论
map
Object.prototype
Object.prototype
map
o = {map: true, image: false}
o.map(fn)
map(o,fn)
Object
Object.map
Object.prototype.map
Object
)
该对象没有原生的,但是这个怎么样:map
Object
var myObject = { 'a': 1, 'b': 2, 'c': 3 };
Object.keys(myObject).forEach(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': 2, 'b': 4, 'c': 6 }
console.log(myObject);
// => { 'a': 1, 'b': 2, 'c': 3 }
Array.prototype.reduce
通过将前一个值与当前值合并,将数组减少为单个值。链由一个空对象初始化。在每次迭代中,都会添加一个新键,其值是键的两倍。{}
myObject
更新
有了新的ES6功能,有一种更优雅的表达方式。objectMap
const objectMap = (obj, fn) =>
Object.fromEntries(
Object.entries(obj).map(
([k, v], i) => [k, fn(v, k, i)]
)
)
const myObject = { a: 1, b: 2, c: 3 }
console.log(objectMap(myObject, v => 2 * v))
评论
map
return
map
forEach
return myObject[value] * 2
.reduce
.map
.reduce
.reduce
myObject
.map
当您不打算使用生成的映射数组时,这不是合适的方法 - 如果您只想产生副作用,例如在您的第一个代码中,您绝对应该改用。forEach
Object.fromEntries
是 ES2019,而不是 ES2015。此外,正如其他人所说,我强烈建议将第一个代码段中的替换为 ,或者其他比.map
forEach
.map
您可以使用 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
没有原生方法,但 lodash#mapValues 会出色地完成这项工作
_.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
// → { 'a': 3, 'b': 6, 'c': 9 }
评论
Object.entries({a: 1, b: 2, c: 3})
_.map()
_.mapValues()
还提供密钥作为第二个参数。这里也不起作用,因为它只返回数组,而不是对象:_.map()
_.map({ 'a': 1, 'b': 2, 'c': 3}, n => n * 3) // [3, 6, 9]
如果你不仅对 ping 值感兴趣,还对键感兴趣,我编写了 Object.map(valueMapper, keyMapper),
其行为方式如下:map
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 }
评论
npm install @mattisg/object.map
我来到这里寻找并将对象映射到数组的答案,并因此得到了这个页面。如果你来这里寻找与我相同的答案,这里是如何映射和反对数组。
您可以使用 map 从对象返回一个新数组,如下所示:
var newObject = Object.keys(myObject).map(function(key) {
return myObject[key];
});
评论
Object.values(myObject)
嘿,写了一个小的映射器函数,可能会有所帮助。
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答案,这里有一个效用函数 (作为评论,它看起来很丑)
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}
公认的答案有两个缺点:
- 它误用了 ,因为 reduce 意味着改变复合类型的结构,而这种情况不会发生。
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 中被重新分配。由于 Javascript 通过共享传递引用值,因此会生成 的浅拷贝。现在,我们可以在不改变父作用域的情况下进行变异。
o
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 指定了迭代器和可迭代协议。但是对象仍然不可迭代,因此不可映射。原因是数据和程序级别的混合。
评论
Array.prototype.reduce
Array.prototype.reduce
fold
map
JS ES10 / ES2019 中的单行代码怎么样?
使用 Object.entries() 和 Object.fromEntries(
):
let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]));
写成函数的相同内容:
function objMap(obj, func) {
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, func(v)]));
}
// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);
此函数也使用递归来平方嵌套对象:
function objMap(obj, func) {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) =>
[k, v === Object(v) ? objMap(v, func) : func(v)]
)
);
}
// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);
在 ES7 / ES2016 中,您不能使用 ,但您可以将 Object.assign
与扩展运算符和计算键名称语法结合使用来实现相同的目的:Objects.fromEntries
let newObj = Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})));
ES6 [美]/ES2015 [美]不允许,但您可以改用 Object.keys
:Object.entries
let newObj = Object.assign({}, ...Object.keys(obj).map(k => ({[k]: obj[k] * obj[k]})));
ES6 还引入了...的
循环,它允许更命令式的样式:
let newObj = {}
for (let [k, v] of Object.entries(obj)) {
newObj[k] = v * v;
}
array.reduce()
而不是 ,你也可以为此使用 reduce:Object.fromEntries
Object.assign
let 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}
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.
console.log(Object.entries(obj2)); // Prints: an empty Array.
for (let key in obj2) {
console.log(key); // Prints: 'a', 'b', 'c'
}
但是,请帮我一个忙,避免继承。:-)
评论
Object.keys
Object.entries({a: 1, b: 2, c: 3})
(o, f)
obj
Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
obj
Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
编辑:使用较新的 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 }
最初的答案是为了演示一个强大的组合器而写的,它使我们能够以不同的方式思考我们的转换mapReduce
m
,映射函数 – 让您有机会在...r
,约简函数 – 此函数将累加器与映射元素的结果相结合
直观地,创建一个我们可以直接插入的新减速器。但更重要的是,我们可以通过使用对象 monoid 和 .mapReduce
Array.prototype.reduce
omap
Object.assign
{}
const identity = x =>
x
const mapReduce = (m, r) =>
(a, x) => r (a, m (x))
const omap = (f = identity, o = {}) =>
Object
.keys (o)
.reduce
( mapReduce
( k => ({ [k]: f (o[k]) })
, Object.assign
)
, {}
)
const square = x =>
x * x
const data =
{ a : 1, b : 2, c : 3 }
console .log (omap (square, data))
// { a : 1, b : 4, c : 9 }
请注意,我们实际上必须编写的程序的唯一部分是映射实现本身——
k => ({ [k]: f (o[k]) })
也就是说,给定一个已知对象和某个键,构造一个对象,其计算属性是调用键的值的结果。o
k
k
f
o[k]
如果我们首先抽象,我们就会瞥见 的测序潜力mapReduce
oreduce
// oreduce : (string * a -> string * b, b, { a }) -> { b }
const oreduce = (f = identity, r = null, o = {}) =>
Object
.keys (o)
.reduce
( mapReduce
( k => [ k, o[k] ]
, f
)
, r
)
// omap : (a -> b, {a}) -> {b}
const omap = (f = identity, o = {}) =>
oreduce
( mapReduce
( ([ k, v ]) =>
({ [k]: f (v) })
, Object.assign
)
, {}
, o
)
一切都是一样的,但现在可以在更高的层次上定义。当然,新的方法使这看起来很傻,但练习对学习者来说仍然很重要。omap
Object.entries
你不会在这里看到它的全部潜力,但我分享这个答案,因为看看它可以应用多少地方很有趣。如果您对它是如何派生的以及它可能有用的其他方式感兴趣,请参阅此答案。mapReduce
评论
Map
Map.entries
Map
我需要一个允许修改密钥的版本(基于 @Amberlamps 和 @yonatanmn 答案);
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);
}
factObject=
{
"asdfasdf": {"color":"red","oldKey":"0"},
"sdfgsdfg": {"color":"green","oldKey":"1"},
"dfghdfgh": {"color":"blue","oldKey":"2"}
}
编辑:稍作改动以传入起始对象 {}。允许它为 [](如果键是整数)
我特别想使用与单个对象数组相同的函数,并希望保持简单。这对我有用:
var mapped = [item].map(myMapFunction).pop();
评论
var mapped = myMapFunction(item)
实现最佳性能。
如果你的对象不经常改变,但需要经常迭代,我建议使用原生Map作为缓存。
// 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);
});
Object.entries 已经在 Chrome、Edge、Firefox 和 beta Opera 中运行,因此它是一项面向未来的功能。 它来自 ES7,因此 polyfill https://github.com/es-shims/Object.entries 它不适用于 IE。
评论
const fn = v => v * 2; const newObj = Object.entries(myObject).reduce((acc, [k,v]) => Object.assign({}, acc, {[k]: fn(v)}), {});
这真的很烦人,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.defineProperty(Object, 'map', {
value: function(obj, fn, ctx) {
const ret = {};
for(let k of Object.keys(obj)){
ret[k] = fn.call(ctx || null, k, obj[k]);
});
return ret;
},
enumerable: false
};
必须一直自己实现这一点是超级烦人的;)
如果你想要一些更复杂的东西,不会干扰 Object 类,请尝试以下操作:
const 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
Object.prototype
Object.defineProperty
enumerable: false
// fairly safe:
Object.map = ...
// not ok (causes all objects to have a "map" property):
Object.prototype.map ...
// fairly safe:
Object.defineProperty(Object.prototype, map, { value: ..., enumerable: false });
评论
Object
const mapObject = (obj, fn) => { [...]; return ret; }
.map
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 }
评论
enumerable
默认为false
最低版本
ES2017 (英语)
Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})
↑↑↑↑↑
ES2019 (英语)
Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]))
↑↑↑↑↑
评论
Object.entries(obj).reduce((a, [k, v]) => [a[k] = v * v, a], {})
Object.entries(obj).reduce((a, [k, v]) => {a[k] = v * v; return a}, {})
我在 Google 搜索中发现这是第一项,试图学习这样做,并认为我会为其他 folsk 分享我最近找到的解决方案,它使用 npm 包不可变。
我认为分享它很有趣,因为 immutable 在他们自己的文档中使用了 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 有其他属性(“Seq 描述了一个惰性操作,允许他们通过不创建中间集合来有效地链接所有高阶集合方法(例如 map 和 filter)的使用”),并且其他一些不可变的 js 数据结构也可能非常有效地完成这项工作。
当然,任何使用此方法的人都必须并且可能想要阅读文档:npm install immutable
https://facebook.github.io/immutable-js/
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>
使用 new _.transform() 转换对象。
如果有人正在寻找将对象映射到新对象或数组的简单解决方案:
// 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]))
);
这可能不适用于所有对象或所有映射函数,但它适用于普通的浅层对象和简单的映射函数,这就是我所需要的。
另一种看法是使用自定义 json stringify 函数,该函数也可以处理深层对象。如果您打算将其作为 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))
你可以使用 method 和 on 数组,但如果你想使用它,那么你可以像下面这样使用它: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}
评论
$
为了更接近 OP 所要求的内容,OP 需要一个对象:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
要有一个 map 方法,myObject.map
类似于 Array.prototype.map,其使用方式如下:
newObject = myObject.map(function (value, label) { return value * value; }); // newObject is now { 'a': 1, 'b': 4, 'c': 9 }
恕我直言,最好的答案(以“接近所要求的”+“不需要不必要的 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);
除了一些人不赞成之外,还可以像这样将解决方案插入原型链中。
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;
}
某些东西,当在仔细的监督下完成时,不应该产生任何不良影响,也不会影响其他对象(即 Array)的方法。map
map
首先,使用 Object.entries(collection) 转换 HTMLCollection。然后它是一个可迭代的,你现在可以在它上面使用 .map 方法。
Object.entries(collection).map(...)
我的回答很大程度上是基于这里评分最高的回答,希望每个人都能理解(在我的GitHub上也有同样的解释)。这就是为什么他用地图进行激励工作的原因:
Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +
')');
该函数的目的是获取一个对象,并使用可用于所有对象(对象和数组)的方法修改对象的原始内容,而不返回数组。JS 中的几乎所有东西都是一个对象,因此,继承管道下游的元素在技术上可能会使用那些可供上层元素使用的元素(反之亦然)。
这样做的原因是 .map 函数返回数组,要求您提供数组的显式或隐式 RETURN,而不是简单地修改现有对象。你基本上通过使用 Object.keys 欺骗程序认为对象是一个数组,这将允许你使用 map 函数,它作用于与各个键关联的值(我实际上不小心返回了数组,但修复了它)。只要没有正常意义上的返回,就不会有原始对象完好无损并按编程修改的数组。
这个特定的程序接受一个名为 images 的对象,并获取其键的值,并附加 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]) 重新分配给所需的值,而不是其他任何值。据我所知,为了防止数组输出,必须重新分配图像[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) => value),并简单地返回存储在该键的任何内容作为该键的值(或者如果您像他一样更改返回值,则乘以 2)在 mapFn(obj)[key],
然后重新定义与 result[key] = mapFn(obj)[key] 中的键关联的原始值
并返回对 result(位于 .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 函数中返回值来复制任何对象。
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)
JavaScript 刚刚有了新方法。Object.fromEntries
例
function mapObject (obj, fn) {
return Object.fromEntries(
Object
.entries(obj)
.map(fn)
)
}
const myObject = { a: 1, b: 2, c: 3 }
const myNewObject = mapObject(myObject, ([key, value]) => ([key, value * value]))
console.log(myNewObject)
解释
上面的代码将 Object 转换为嵌套的数组 (),您可以映射它。 将 Array 转换回 Object。[[<key>,<value>], ...]
Object.fromEntries
这种模式很酷的地方在于,您现在可以在映射时轻松地将对象键考虑在内。
文档
浏览器支持
Object.fromEntries
目前仅受这些浏览器/引擎支持,但仍有可用的 polyfills(例如 @babel/polyfill)。
评论
Object.fromEntries
Object.entries
Object.entries
Object.fromEntries
Array.map()
(value, key)
Array.map()
Array.forEach()
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' ]
我只处理字符串以减少豁免:
Object.keys(params).map(k => typeof params[k] == "string" ? params[k] = params[k].trim() : null);
TypeScript 中的对象映射器
我喜欢使用这样的示例,但是它们仍然不是很容易使用。使用然后查找的答案实际上是在进行多次查找,这些查找可能不是必需的。Object.fromEntries
Object.keys
key
我希望有一个函数,但我们可以创建自己的函数并调用它,并能够修改两者和:Object.map
objectMap
key
value
用法 (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
* 部分功劳归功于亚历山大-米尔斯的回答。
评论
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}]}]}
此函数以递归方式遍历对象和对象数组。如果返回 undefined,则可以删除属性
只需使用以下命令即可将对象转换为数组:
您可以将对象值转换为数组:
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);
现在您可以执行正常的数组操作,包括“map”函数
评论
var myObject = { 'a': 1, 'b': 2, 'c': 3 };
Object.keys(myObject).filter((item) => myObject[item] *= 2)
console.log(myObject)
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 }
评论
使用以下映射函数定义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);
我需要一个函数来选择性地映射不仅(也不完全)值,还有键。原始对象不应更改。该对象也只包含基元值。
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}
这是另一个版本,它允许映射函数根据当前键和值声明任意数量的新属性(键和值)。E:现在也适用于数组。
Object.defineProperty(Object.prototype, 'mapEntries', {
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.mapEntries( 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.mapEntries( duplicate ) );
// [ "a", "aa", "b", "bb", "c", "cc" ]
异步,有人吗?
尽管有大量评论,但我没有找到使用映射器的解决方案。这是我的。async
使用 p-map,一个受信任的 (@sindresorhus) 和小依赖项。
(请注意,没有选项传递给 。如果需要调整并发/错误处理,请参阅文档)。p-map
打字稿:
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);
};
};
使用示例:
(高度做作,无错误处理,无类型)
// Our object in question.
const ourFavouriteCharacters = {
me: "luke",
you: "vader",
everyone: "chewbacca",
};
// An async function operating on the object's values (in this case, strings)
const fetchCharacter = (charName) =>
fetch(`https://swapi.dev/api/people?search=${charName}`)
.then((res) => res.json())
.then((res) => res.results[0]);
// `objectMapAsync` will return the final mapped object to us
// (wrapped in a Promise)
objectMapAsync(ourFavouriteCharacters, fetchCharacter).then((res) =>
console.log(res)
);
评论
const array = Object.keys(object)
//returns all keys as array ["key", "key"]
const array = Object.values(object)
//returns all values as array ["value", "value"]
const array = Object.entries(object)
//returns all entries as array = [["key","value"], ["key","value"]]
对结果使用 Map。
array.map()
这是我这样做的方式,结果在效率和可读性方面是值得的。
myObject = { 'a': 1, 'b': 2, 'c': 3 }
const newObject = Object.entries(myObject)
.map(([key, value]) => `${key}: ${value * value}`)
.join(', ');
console.log(newObject)
上一个:写入 Node.js 中的文件
评论
Object.keys
Object.getOwnPropertyNames
Object.keys
Object.getOwnPropertyNames
Object.keys