Mappa su chiavi di conservazione degli oggetti


129

La mapfunzione in underscore.js, se chiamata con un oggetto javascript, restituisce una matrice di valori mappati dai valori dell'oggetto.

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

c'è un modo per preservare le chiavi? cioè, voglio una funzione che ritorni

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

Se, come me, sei venuto qui alla ricerca di una funzione simile a "mapValues" che cambia l'oggetto reale invece di restituirne uno nuovo, controlla questa semplice soluzione: stackoverflow.com/questions/30894044/…
Michael Trouw,

Risposte:


228

Con Underscore

Underscore fornisce una funzione _.mapObjectper mappare i valori e conservare le chiavi.

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

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

DEMO


Con Lodash

Lodash fornisce una funzione _.mapValuesper mappare i valori e conservare le chiavi.

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

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

DEMO


Ci sono stati sforzi per ottenere una funzione _.mapValues ​​nel carattere di sottolineatura: problema rilevante , richiesta pull per _.mapValues . Spero che ciò
avvenga

mi sembra che tu stia trasformando un OGGETTO in un oggetto o sono fuori di testa?
jsh,

@jsh In questo caso, _.map()sta tornando [['one', 3], ['two', 6], ['three', 9]], che è una matrice di array, e lo _.object()sta trasformando nuovamente in un oggetto.
Jezen Thomas,

56

Sono riuscito a trovare la funzione richiesta in lodash, una libreria di utilità simile a underscore.

http://lodash.com/docs#mapValues

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

Crea un oggetto con le stesse chiavi dell'oggetto e dei valori generati eseguendo ciascuna proprietà enumerabile dell'oggetto tramite il callback. Il callback è associato a thisArg e invocato con tre argomenti; (valore, chiave, oggetto).


19

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

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


13

So che questo è vecchio, ma ora Underscore ha una nuova mappa per gli oggetti:

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

Ovviamente puoi costruire una mappa flessibile per matrici e oggetti

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}

5
Nota per gli utenti lodash: jdalton ha deciso di interrompere la compatibilità con underscore.js per questa modifica. lodash non supporterà mapObject; guarda invece il mapValuesmetodo lodash .
Mark Amery,

13

Che ne dici di questa versione in semplice JS ( ES6 / ES2015 )?

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

jsbin

Se vuoi mappare ricorsivamente un oggetto (mappa obj nidificato), puoi farlo in questo modo:

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

jsbin

Da ES7 / ES2016 puoi usare Object.entriesinvece di Object.keysquesto:

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

5

So che è passato molto tempo, ma manca ancora la soluzione più ovvia tramite fold (ovvero ridurre in js), per completezza la lascerò qui:

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}

Sono d'accordo con l'uso della libreria Lodash, ma i programmatori usano questo tipo di librerie e non sanno come si possano ottenere queste cose in JS vaniglia. Quindi apprezzo la tua risposta!
cyonder

3

_.map restituisce una matrice, non un oggetto.

Se vuoi un oggetto, stai meglio usando una funzione diversa, come each; se vuoi davvero usare la mappa potresti fare qualcosa del genere:

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

ma questo è confuso, quando vedendo mapuno ci si aspetterebbe di avere un array come risultato e quindi fare qualcosa con esso.


Ho avuto la sensazione di leggere i documenti che non sarebbe naturale provare questo in underscore.js. Penso che il mio caso d'uso sia abbastanza naturale, perché non lo supportano?
Xuanji,

Probabilmente un motivo potrebbe essere maputilizzato per modificare un input producendo un array come output, è possibile comporre _.objecte _.mapcome @GG. ha scritto, ma è una questione di gusti a questo punto.
Alberto Zaccagni,

3

Penso che tu voglia una funzione mapValues (per mappare una funzione sui valori di un oggetto), che è abbastanza facile da implementare:

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};

2
const mapObject = (obj = {}, mapper) =>
  Object.entries(obj).reduce(
    (acc, [key, val]) => ({ ...acc, [key]: mapper(val) }),
    {},
  );

Stavo per aggiungere questa risposta da solo. Sono contento di averlo fatto scorrere!
Bill Criswell,

0

Una correzione mista per il bug della mappa di sottolineatura : P

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

Una soluzione semplice che mantiene la chiave giusta e ritorna come oggetto. È ancora usata nello stesso modo in cui io ospite potresti usare questa funzione per sovrascrivere la funzione bug. _.map

o semplicemente come me l'ho usato come mixin

_.mapobj ( options , function( val, key, list ) 

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.