2016-01-28 8 views
9

https://lodash.com/docs#mapKeysCome mappare in modo approfondito le chiavi dell'oggetto con JavaScript (lodash)?

È possibile mappare le chiavi di un oggetto in profondità utilizzando Lodash? In caso contrario, esiste un'altra libreria che fornisce questa funzionalità (se raggruppata con altre funzionalità di iterazione e manipolazione profonda, ancora meglio!)? Altrimenti, come si dovrebbe implementare questo? La principale lotta che vedo è nell'identificare oggetti chiave/valore puri che siano sicuri, profondamente iterabili. È facile lanciare Array, ma è importante notare che la funzione non dovrebbe tentare di eseguire iterazioni profonde su altri oggetti come una regex, ad esempio.

Previsto risultato-

var obj = { a: 2, b: { c: 2, d: { a: 3 } } }; 
_.deepMapKeys(obj, function (val, key) { 
    return val + '_hi'; 
}); 
// => { a_hi: 2, b_hi: { c_hi: 2, d_hi: { a_hi: 3 } } } 

risposta

21

Ecco come si può fare in lodash:

_.mixin({ 
    'deepMapKeys': function (obj, fn) { 

     var x = {}; 

     _.forOwn(obj, function(v, k) { 
      if(_.isPlainObject(v)) 
       v = _.deepMapKeys(v, fn); 
      x[fn(v, k)] = v; 
     }); 

     return x; 
    } 
}); 

ed ecco un mixin più astratto, che si applica in modo ricorsivo ogni data mapper:

_.mixin({ 
    deep: function (obj, mapper) { 
     return mapper(_.mapValues(obj, function (v) { 
      return _.isPlainObject(v) ? _.deep(v, mapper) : v; 
     })); 
    }, 
}); 

Utilizzo (restituisce lo stesso come sopra):

obj = _.deep(obj, function(x) { 
    return _.mapKeys(x, function (val, key) { 
     return key + '_hi'; 
    }); 
}); 

Un'altra opzione, con la sintassi più elegante:

_.mixin({ 
    deeply: function (map) { 
     return function(obj, fn) { 
      return map(_.mapValues(obj, function (v) { 
       return _.isPlainObject(v) ? _.deeply(map)(v, fn) : v; 
      }), fn); 
     } 
    }, 
}); 


obj = _.deeply(_.mapKeys)(obj, function (val, key) { 
    return key + '_hi'; 
}); 
+0

Questa è un'ottima soluzione, quindi la inviterò. Tuttavia, trovo la risposta accettata più semplice nel risolvere l'opzione, quindi questo è l'approccio che raccomanderei. –

+0

@TejasManohar: beh, hai chiesto un codice basato su lodash ed è in grado di distinguere tra oggetti semplici e dattilografati ... la risposta accettata non è né l'uno né l'altro. – georg

+0

Hai ragione. Ho cambiato questo. –

1

EDIT: Questo sarà mappare i valori di oggetti, non le sue chiavi. Ho frainteso la domanda.


function deepMap (obj, cb) { 
    var out = {}; 

    Object.keys(obj).forEach(function (k) { 
     var val; 

     if (obj[k] !== null && typeof obj[k] === 'object') { 
     val = deepMap(obj[k], cb); 
     } else { 
     val = cb(obj[k], k); 
     } 

     out[k] = val; 
    }); 

    return out; 
} 

e usarlo come

var lol = deepMap(test, function (v, k) { 
    return v + '_hi'; 
}); 

Sarà ricorsivamente iterare su un oggetto possedere proprietà enumerabili e chiamare un CB passandogli il valore corrente e la chiave. I valori restituiti sostituiranno il valore esistente per il nuovo oggetto. Non muta l'oggetto originale.

See violino: https://jsfiddle.net/1veppve1/

+1

È importante notare che questo restituisce un nuovo oggetto con valori diversi, non le chiavi, come richiesto nella domanda.Detto questo, si tratta di un semplice cambiamento, ed esprime la comprensione concettuale, quindi salverò un downvote :) –

+0

@TejasManohar Dannazione, mi scusi, ho frainteso il punto. Pensavo che tu stia mappando il valore non chiavi. Aggiungerò una modifica in modo che gli altri non si confondano. – ste2425

+0

La soluzione ha troppo codice ridondante –

1

In estensione della risposta di Georg, ecco quello che sto usando. Questo mixin esteso aggiunge la possibilità di mappare le matrici di oggetti all'interno dell'oggetto, un cambiamento semplice ma importante.

_.mixin({ 
    deeply: function (map) { 
     return function (obj, fn) { 
     return map(_.mapValues(obj, function (v) { 
      return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ? v.map(function(x) { 
      return _.deeply(map)(x, fn); 
      }) : v; 
     }), fn); 
     } 
    }, 
    }); 
0

Ho aggiunto un piccolo miglioramento da Chris Jones's answer.

Il seguente codice corregge alcuni risultati non previsti degli elementi dell'array.

_.mixin({ 
    deeply: function (map) { 
    var deeplyArray = function (obj, fn) { 
     return obj.map(function(x) { 
     return _.isPlainObject(x) ? _.deeply(map)(x, fn) : x; 
     }) 
    } 

    return function (obj, fn) { 
     if (_.isArray(obj)) { 
     return deeplyArray(obj, fn); 
     } 

     return map(_.mapValues(obj, function (v) { 
     return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ? 
      deeplyArray(v, fn) : v; 
     }), fn); 
    } 
    }, 
}); 
Problemi correlati