Kaartfunctie voor objecten (in plaats van arrays)

Ik heb een object:

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

Ik ben op zoek naar een inheemse methode, vergelijkbaar met Array.prototype.mapdie als volgt zou worden gebruikt:

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

Heeft Javascript zo’n mapfunctie voor objecten? (Ik wil dit voor node.js, dus ik geef niet om cross-browser problemen.)


1, Autoriteit 100%

Er is geen native mapnaar de Objectobject, maar hoe zit het met dit:

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 }

2, Autoriteit 20%

Wat dacht u van een one-liner in JS ES10 / ES2019 ?

Gebruik maken van Object.entries()en Object.fromEntries():

let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]));

Hetzelfde geschreven als een functie:

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

Deze functie gebruikt recursieook om geneste objecten vierkant te maken:

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

Met ES7 / ES2016kunt u Objects.fromEntriesniet gebruiken, maar u kunt hetzelfde bereiken met Object.assignin combinatie met spread-operatorsen berekende sleutelnamensyntaxis:

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

ES6 / ES2015Staat Object.entriesniet toe, maar u kunt Object.keysin plaats daarvan:

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

ES6 heeft ook for...ofloops, die een meer Bergelijkheid toestaan ​​stijl:

let newObj = {}
for (let [k, v] of Object.entries(obj)) {
  newObj[k] = v * v;
}

array.reduce ()

In plaats van Object.fromEntriesen Object.assignU kunt ook Verminder hiervoor:

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

geërfde eigenschappen en de prototype ketting:

In sommige zeldzame situatie moet u mogelijk een -es-achtig –object in kaart brengen dat eigenschappen van een geërfd object op zijn prototype-keten . In dergelijke gevallen Object.keys()en Object.entries()niet, omdat deze functies niet de prototype-keten bevatten.

Als u in kaart moet brengen -eigenschappen, kunt u for (key in myObj) {...}.

Hier is een voorbeeld van een dergelijke situatie:

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'
}

Doe me echter een plezier en vermijd erfenis. 🙂


Antwoord 3, autoriteit 7%

Geen native methoden, maar lodash#mapValueszal het werk uitstekend doen

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

Antwoord 4, autoriteit 3%

Het is vrij eenvoudig om er een te schrijven:

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

met voorbeeldcode:

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

NB: deze versie laat je ook (optioneel) de thiscontext instellen voor de callback, net als de Arraymethode.

EDIT– gewijzigd om het gebruik van Object.prototypete verwijderen, om ervoor te zorgen dat het niet botst met een bestaande eigenschap met de naam mapop het voorwerp.


Antwoord 5

U kunt Object.keysEn dan forEachover de geretourneerde reeks van sleutels:

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

of op een meer modulaire manier:

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

Merk op dat Object.keysretourneert een array die alleen de eigen traaglijke eigenschappen van het object bevat, waardoor het gedraagt ​​zich als een for..inlus met een hasOwnPropertyControleren.


6

Ik kwam hier op zoek naar te vinden en te beantwoorden voor het in kaart brengen van een object naar een array en kreeg deze pagina als resultaat. In het geval dat je hier op zoek bent naar hetzelfde antwoord, was ik, hier is hoe je kunt in kaart brengen en bezwaar maken aan een array.

U kunt kaart gebruiken om een ​​nieuwe array van het object zoals SO te retourneren:

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

7

Javascript heeft net de nieuwe Object.fromEntriesMethod.

Voorbeeld

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)

8

Het geaccepteerde antwoord heeft twee nadelen:

  • Het maakt misbruik van Array.prototype.reduce, omdat verkleinen betekent dat de structuur van een samengesteld type wordt gewijzigd, wat in dit geval niet gebeurt.
  • Het is niet bijzonder herbruikbaar

Een ES6/ES2015 functionele benadering

Houd er rekening mee dat alle functies in kerrievorm zijn gedefinieerd.

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

Antwoord 9

Minimale versie (es6):

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

Antwoord 10

Voor maximale prestaties.

Als uw object niet vaak verandert, maar vaak moet worden herhaald, raad ik u aan een native kaart als cache te gebruiken.

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

Antwoord 11

je kunt de methode mapen forEachgebruiken op arrays, maar als je het op Objectwilt gebruiken, kun je het gebruiken met twist zoals hieronder:

Javascript (ES6) gebruiken

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 gebruiken

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}

Of je kunt ook andere loops gebruiken, zoals de methode $.each, zoals in onderstaand voorbeeld:

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

Antwoord 12

U kunt een object eenvoudig naar een array converteren door het volgende te gebruiken:

U kunt de objectwaarden converteren naar een array:

myObject = { 'a': 1, 'b': 2, 'c': 3 };
let valuesArray = Object.values(myObject);
console.log(valuesArray);

Antwoord 13

De map functionbestaat niet op het Object.prototypemaar je kunt het wel zo emuleren

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

Antwoord 14

EDIT: De canonieke manier om nieuwere JavaScript-functies te gebruiken is –

const identity = x =>
  x
const omap = (f = identity, o = {}) =>
  Object.fromEntries(
    Object.entries(o).map(([ k, v ]) =>
      [ k, f(v) ]
    )
  )

Waarbij oeen object is en fuw toewijzingsfunctie. Of we zouden kunnen zeggen, gegeven een functie van a -> b, en een object met waarden van het type a, produceren een object met waarden van het type b. Als pseudo-typehandtekening –

// omap : (a -> b, { a }) -> { b }

Het oorspronkelijke antwoord is geschreven om een krachtige combinator te demonstreren, mapReduce, waarmee we op een andere manier naar onze transformatie kunnen kijken

  1. m, de mappingfunctie – geeft je de kans om het binnenkomende element te transformeren voordat…
  2. r, de reducerendefunctie – deze functie combineert de accumulator met het resultaat van het toegewezen element

Intuïtief maakt mapReduceeen nieuw verloopstuk dat we rechtstreeks kunnen aansluiten op Array.prototype.reduce. Maar wat nog belangrijker is, we kunnen onze objectfunctie-implementatie omapduidelijk implementeren door gebruik te maken van de objectmonoïde, Object.assignen {}.

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 }

Antwoord 15

Ik kwam dit tegen als een eerste item in een Google-zoekopdracht om dit te leren, en dacht dat ik het met andere mensen zou delen die onlangs de oplossing vonden die ik vond, die het npm-pakket onveranderlijk gebruikt.

Ik denk dat het interessant is om te delen omdat immutable de EXACTE situatie van het OP gebruikt in hun eigen documentatie – het volgende is niet mijn eigen code, maar is overgenomen uit de huidige immutable-js-documentatie:

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 } 

Niet dat Seq andere eigenschappen heeft (“Seq beschrijft een luie operatie, waardoor ze efficiënt gebruik kunnen maken van alle hogere-orde verzamelmethoden (zoals kaart en filter) door geen tussenliggende verzamelingen te maken”) en dat een andere onveranderlijke -js datastructuren kunnen het werk ook behoorlijk efficiënt doen.

Iedereen die deze methode gebruikt, moet natuurlijk npm install immutableen wil misschien de documenten lezen:

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


Antwoord 16

Gebaseerd op het antwoord van @Amberlamps, hier is een hulpprogramma-functie
(als opmerking zag het er lelijk uit)

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

en het gebruik is:

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}

Antwoord 17

Mijn reactie is grotendeels gebaseerd op de best beoordeelde reactie hier en hopelijk begrijpt iedereen het (heb dezelfde uitleg ook op mijn GitHub). Dit is waarom zijn impementatie met kaart werkt:

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

Het doel van de functie is om een object te nemen en de originele inhoud van het object te wijzigen met behulp van een methode die beschikbaar is voor alle objecten (zowel objecten als arrays) zonder een array te retourneren. Bijna alles binnen JS is een object, en om die reden kunnen elementen verderop in de pijplijn van overerving mogelijk technisch gebruik maken van de elementen die beschikbaar zijn voor degenen die hogerop in de rij staan (en omgekeerd lijkt het).

De reden dat dit werkt, is omdat de .map-functies een array retourneren VEREIST dat je een expliciete of impliciete RETURN van een array opgeeft in plaats van simpelweg een bestaand object te wijzigen. Je laat het programma in wezen denken dat het object een array is door Object.keys te gebruiken, waarmee je de kaartfunctie kunt gebruiken met de waarden waaraan de individuele sleutels zijn gekoppeld (ik heb eigenlijk per ongeluk arrays geretourneerd, maar het gerepareerd). Zolang er geen terugkeer in de normale zin is, wordt er geen array gemaakt met het oorspronkelijke object nog intact en gewijzigd zoals geprogrammeerd.

Dit specifieke programma neemt een object genaamd afbeeldingen en neemt de waarden van zijn sleutels en voegt url-tags toe voor gebruik binnen een andere functie. Origineel is dit:

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

…en aangepast is dit:

var images = { 
snow: url('https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305'),     
sunny: url('https://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') 
};

De originele structuur van het object wordt intact gelaten, waardoor normale toegang tot eigendommen mogelijk is zolang er geen terugkeer is. Laat het NIET een array retourneren zoals normaal en alles komt goed. Het doel is om de oorspronkelijke waarden (afbeeldingen [sleutel]) OPNIEUW TOEWIJZEN aan wat gewenst is en niet aan iets anders. Voor zover ik weet, MOET er, om array-output te voorkomen, een HERTOEPASSING van afbeeldingen [sleutel] zijn en geen impliciet of expliciet verzoek om een array te retourneren (variabele toewijzing doet dit en ging voor mij heen en weer).

BEWERKEN:

Ga in op zijn andere methode met betrekking tot het maken van nieuwe objecten om te voorkomen dat het oorspronkelijke object wordt gewijzigd (en hertoewijzing lijkt nog steeds nodig te zijn om te voorkomen dat per ongeluk een array als uitvoer wordt gemaakt). Deze functies gebruiken de syntaxis van de pijl en zijn bedoeld als u gewoon een nieuw object wilt maken voor toekomstig gebruik.

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

De manier waarop deze functies werken is als volgt:

mapFn neemt de functie die later moet worden toegevoegd (in dit geval (waarde) => waarde) en retourneert eenvoudig wat daar is opgeslagen als een waarde voor die sleutel (of vermenigvuldigd met twee als u de geretourneerde waarde wijzigt zoals hij deed ) in mapFn(obj)[sleutel],

en herdefinieert vervolgens de oorspronkelijke waarde die is gekoppeld aan de sleutel in result[key] = mapFn(obj)[key]

en retourneert de bewerking die op resultaat is uitgevoerd (de accumulator die zich tussen de haakjes bevindt die aan het einde van de functie .reduce is gestart).

Dit alles wordt uitgevoerd op het gekozen object en NOG STEEDS KAN er GEEN impliciete aanvraag voor een geretourneerde array zijn en werkt alleen bij het opnieuw toewijzen van waarden voor zover ik weet. Dit vereist wat mentale gymnastiek, maar vermindert de benodigde coderegels, zoals hierboven te zien is. Uitvoer is precies hetzelfde als hieronder te zien is:

{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"}

Houd er rekening mee dat dit werkte met NON-NUMBERS. U KUNT ELK object dupliceren door EENVOUDIG DE WAARDE TE RETOURNEREN in de mapFN-functie.


Antwoord 18

Als je geïnteresseerd bent in mapping, niet alleen waarden maar ook sleutels, heb ik Object.map(valueMapper, keyMapper), dat zich zo gedraagt:

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 }

Antwoord 19

Ik had een versie nodig waarmee ik ook de sleutels kon wijzigen (gebaseerd op de antwoorden van @Amberlamps en @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"}
}

Bewerken: kleine wijziging om het startobject {} door te geven. Staat toe dat het [] is (als de sleutels gehele getallen zijn)


Antwoord 20

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 }

Antwoord 21

Om beter te reageren op wat precieshet OP vroeg, wil het OP een object:

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

om een kaartmethode myObject.mapte hebben,

vergelijkbaar met Array.prototype.map die als volgt zou worden gebruikt:

newObject = myObject.map(functie (waarde, label) {
  retourwaarde * waarde;
});
// newObject is nu { 'a': 1, 'b': 4, 'c': 9 }

Het imhobeste antwoord (gemeten in termen van “dicht bij wat wordt gevraagd” + “geen ES{5,6,7} onnodig vereist”) zou zijn :

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

De bovenstaande code vermijdt het opzettelijk gebruik van taalfuncties, die alleen beschikbaar zijn in recente ECMAScript-edities. Met de bovenstaande code kan het probleem als volgt worden opgelost:

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

Antwoord 22

Converteer eerst uw HTMLCollection met Object.entries(collection). Dan is het een iterable die je nu kunt gebruiken met de .map-methode.

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

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


Antwoord 23

Object Mapper in TypeScript

Ik hou van de voorbeelden die Object.fromEntriesgebruiken, zoals deze, maar toch , ze zijn niet erg gemakkelijk te gebruiken. De antwoorden die Object.keysgebruiken en vervolgens de keyopzoeken, doen in feite meerdere opzoekingen die misschien niet nodig zijn.

Ik wou dat er een Object.map-functie was, maar we kunnen onze eigen maken en deze objectMapnoemen met de mogelijkheid om beide keyen value:

Gebruik (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' }

Code (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;
}

Als je TypeScript niet gebruikt, kopieer dan de bovenstaande code naar TypeScript Playgroundom het JavaScript te krijgen code.

Ook de reden dat ik keySelectorna valSelectorin de parameterlijst plaats, is omdat het optioneel is.

* Een deel van het krediet gaat naar het antwoordvan alexander-mills.


Antwoord 24

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

Deze functie gaat recursief door het object en de arrays van objecten. Attributen kunnen worden verwijderd als ze ongedefinieerd worden geretourneerd


Antwoord 25

Hey heeft een kleine mapper-functie geschreven die zou kunnen helpen.

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

Antwoord 26

Als iemand op zoek was naar een eenvoudige oplossing die een object toewijst aan een nieuw object of aan een array:

// 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]))
);

Dit werkt misschien niet voor alle objecten of alle kaartfuncties, maar het werkt voor gewone, ondiepe objecten en eenvoudige kaartfuncties, en dat is alles wat ik nodig had.


Antwoord 27

Een andere kijk hierop is het gebruik van een aangepaste json stringify-functie die ook op diepe objecten kan werken. Dit kan handig zijn als je het toch als json op de server wilt posten

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

Antwoord 28

Ik behandel alleen strings om vrijstellingen te verminderen:

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

Antwoord 29

Ik had een functie nodig om optioneel niet alleen (noch uitsluitend) waarden, maar ook sleutels toe te wijzen. Het oorspronkelijke object mag niet veranderen. Het object bevatte ook alleen primitieve waarden.

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

Gebruik. Geef een keymapper en een valuemapper-functie door:

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

Other episodes