Elegant array conversion in Javascript

What an elegant way - purely functional, ideal - to convert (reduce?) This array:

var in = [ { a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' } ] 

In it:

 var out = [ { a: 1, x: 'foo', y: 'goo' }, { a: 2, x: 'hoo', y: 'joo' } ] 

The logic is that all elements should be combined based on their property a , and all properties b and c are key / value pairs, respectively, which should be combined into one object based on their common a value.

+5
source share
5 answers

You can use the hash object and reduce to wrap the hash like this:

 const arr = [ { a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' } ]; let result = Object.values( // the result is the values of the hash object arr.reduce((hash, o) => { // hash is a hash object that make it easier to group the result hash[oa] = hash[oa] || {a: oa}; // if there is no object in the hash that have the value of the key a equal to oa, then create a new one hash[oa][ob] = oc; // set the value of the key stored in ob to oc return hash; }, {}) ); console.log(result); 
+7
source

You can use closure with Map

 var input = [{ a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' }], output = input.reduce((map => (r, o) => (!map.has(oa) && map.set(oa, r[r.push({ a: oa }) - 1]), map.get(oa)[ob] = oc, r))(new Map), []); console.log(output); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
+5
source

You can use forEach and Object.assign to group a , and then map to return the values ​​of the object.

 var data = [ { a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' } ] var r = {} data.forEach(e => r[ea] = Object.assign((r[ea] || {}), {a: ea, [eb]: ec})) r = Object.keys(r).map(e => r[e]) console.log(r) 
+2
source

Not sure if the approach is elegant or functional, although it returns the expected result using the for..of , Array.prototype.some() and Object.assign()

 function props(array, key, prop1, prop2) { let arr = []; for (let obj of array) { let o = {}; for (let {[key]:_key, [prop1]:_prop1, [prop2]:_prop2} of [obj]) { o[_prop1] = _prop2; o[key] = _key; } if (!arr.some(p => p[key] === o[key])) arr.push(o); for (let prop of arr) { if (prop[key] == o[key]) { prop = Object.assign(prop, o) } } } return arr } var _in = [ { a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' } ]; console.log(props(_in, "a", "b", "c")); 
0
source

I like the answers provided, but here is my attempt. I find this to be more readable, but uses Object.assign and Object.values

 const input = [ { a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' } ] const map = input.reduce((acc, obj) => { const [a, key, value] = Object.values(obj) const newObj = {a, [key]: value} if (acc[a]) { Object.assign(acc[a], newObj) } else { acc[a] = newObj } return acc }, {}) console.log(Object.values(map)) 
0
source

Source: https://habr.com/ru/post/1264132/


All Articles