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.