lodash: mapeo de matriz a objeto


90

¿Hay una función lodash incorporada para tomar esto?

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

Y da salida a esto:

var output = {
    foo: 'bar',
    baz: 'zle'
};

En este momento solo estoy usando Array.prototype.reduce():

function toHash(array, keyName, valueName) {
    return array.reduce(function(dictionary, next) {
        dictionary[next[keyName]] = next[valueName];
        return dictionary;
    }, {});
}

toHash(params, 'name', 'input');

Me pregunto si hay un atajo pesado.

Respuestas:


132

Otra forma con lodash 4.17.2

_.chain(params)
    .keyBy('name')
    .mapValues('input')
    .value();

o

_.mapValues(_.keyBy(params, 'name'), 'input')

o con _.reduce

_.reduce(
    params,
    (acc, { name, input }) => ({ ...acc, [name]: input }),
    {}
)

@Akrikos _.keyBytransformará toda la matriz en un objeto, mientras que la pregunta se trata principalmente de tener un elemento de cada objeto en la matriz como clave y otro elemento como valor. Si _.keyByse usa, todos los valores serán objetos.
Mustafa Ehsan Alokozay

Gracias @MustafaEhsanAlokozay Tienes razón, esa respuesta no hace exactamente lo correcto. Eliminaré mi comentario porque no es útil. Eso puede hacer que tu comentario se vea extraño, pero es mejor que mi comentario incorrecto permanezca por más tiempo.
Akrikos

53

Debería utilizar _.keyBy para convertir fácilmente una matriz en un objeto.

Documentos aquí

Ejemplo de uso a continuación:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
console.log(_.keyBy(params, 'name'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Si es necesario, puede manipular la matriz antes de usar _.keyBy o el objeto después de usar _.keyBy para obtener el resultado exacto deseado.


2
Mire primero esto para comprender la respuesta más votada por stasovlas.
Roman Susi

3
Esta es una buena respuesta, pero NO responde a la pregunta. Los valores deben ser cadenas, no objetos.
Dem Pilafian

34

Sí, está aquí , usando_.reduce

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

_.reduce(params , function(obj,param) {
 obj[param.name] = param.input
 return obj;
}, {});

Una vez más, reduce()aparece otro caso de uso. ¡Manera inteligente de hacerlo!
Dan

¿Alguien tiene la versión mecanografiada de esto?
mr.bjerre

La realidad es que es matemáticamente cierto que puede implementar literalmente cualquier acción de iteración usando reducir / inyectar, ya que reducir es isomorfo a una lista. Sin embargo, esa flexibilidad tiene un precio en legibilidad. No lo use a _.reducemenos que exprese con precisión lo que está tratando de hacer: oscurece significativamente el punto del código en cualquier otro caso. Personalmente prefiero la _.zipObjectsolución de @djechlin; de lo contrario, el enfoque _.keyBy/ _.mapValues.
Robert Fischer

15

Esto parece un trabajo para Object.assign:

const output = Object.assign({}, ...params.map(p => ({[p.name]: p.input})));

Editado para envolver como una función similar a los OP, esto sería:

const toHash = (array, keyName, valueName) => 
    Object.assign({}, ...array.map(o => ({[o[keyName]]: o[valueName]})));

(Gracias a Ben Steward, buen pensamiento ...)


Tal vez envuelva eso en una función principal para que el usuario pueda determinar qué claves se usarían pasándolas, como lo hizo el OP.
Ben Steward


10

Esto probablemente sea más detallado de lo que desea, pero está solicitando una operación un poco compleja, por lo que el código real podría estar involucrado (el horror).

Mi recomendación, con zipObjecteso es bastante lógico:

_.zipObject(_.map(params, 'name'), _.map(params, 'input'));

Otra opción, más hacky, usando fromPairs:

_.fromPairs(_.map(params, function(val) { return [val['name'], val['input']));

La función anónima muestra la piratería: no creo que JS garantice el orden de los elementos en la iteración del objeto, por lo que la llamada .values()no funcionará.


No veo nada raro en el uso fromPairsy, de values()hecho , llamar no sirve. Al menos desde el punto de vista de la legibilidad.
x-yuri

6

Otra forma con lodash

crear pares, y luego construir un objeto o ES6 Mapfácilmente

_(params).map(v=>[v.name, v.input]).fromPairs().value()

o

_.fromPairs(params.map(v=>[v.name, v.input]))

Aquí hay un ejemplo de trabajo


1
Lo bueno de esta solución es que también es factible en ES simple:Object.fromEntries(params.map(v => [v.name, v.input]))
fregante

@fregante, Chrome 73+ solo caniuse.com/?search=fromEntries
d9k

6

También puede resolver sin usar ninguna función lodash como esta:

let paramsVal = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
let output = {};

paramsVal.forEach(({name, input})=>{
  output[name] = input;
})


console.log(output);

ingrese la descripción de la imagen aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.