I have an array of arrays. How do I convert them to an array of objects grouped together?
var abc = [ ['apple', 'fruit'], ['banana', 'fruit'], ['grapes', 'fruit'], ['red', 'color'], ['blue', 'color'], ['black', 'color'] ] abc = abc.map(function(item) { return { value: item[0], color: item[1] } }) colors = abc.filter(function(item) { return item.color === 'color' }) fruits = abc.filter(function(item) { return item.color === 'fruit' }) var result = [{ group: 'color', value: colors.map(function(item) { return item.value }) }, { group: 'fruit', value: fruits.map(function(item) { return item.value }) }] console.log(result)
My expected output is:
var abc = [
{
group: 'color',
value: ['red', 'blue', 'black']
},
{
group: 'fruit',
value: ['apple', 'banana', 'grapes']
}]
Is there an easier way to achieve this?
I can use lodash too. Please advise.
Here's an approach using reduce
and map
. reduce
performs an aggregation by group
mapped to an array of values. Object.entries()
and map
transform this grouping into the desired format as an array of objects.
var abc = [ ['apple', 'fruit'], ['banana', 'fruit'], ['grapes', 'fruit'], ['red', 'color'], ['blue', 'color'], ['black', 'color'] ]; const result = Object.entries( abc.reduce((a, e) => { if (!(e[1] in a)) { a[e[1]] = []; } a[e[1]].push(e[0]); return a; }, {}) ).map(e => ({group: e[0], value: e[1]})) ; console.log(result);
You could group with lodash by the index and map the values of the other index.
var data = [['apple', 'fruit'], ['banana', 'fruit'], ['grapes', 'fruit'], ['red', 'color'], ['blue', 'color'], ['black', 'color']], result = _(data) .groupBy(1) .map((array, group) => ({ group, value: _.map(array, 0) })) .sortBy('group') .value(); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Here's a method I've described in a comment to your question:
group
value If not found, you create it
abc.reduce((arr, input) => { const index = arr.findIndex(i => i.group === input[0]) return [ ...(index > -1 ? [ ...arr.slice(0, index), { group: input[0], value: [ ...arr[index].value, input[1] ] }, ...arr.slice(index + 1) ] : [ ...arr, { group: input[0], value: [ input[1] ] } ]) ] }, [])
Here is way to do it with an ES6 Map
as intermediate data structure:
var abc = [['apple', 'fruit'],['banana', 'fruit'],['grapes', 'fruit'],['red', 'color'],['blue', 'color'],['black', 'color']]; const groups = new Map(abc.map(a =>[a[1], []])); abc.forEach(a => groups.get(a[1]).push(a[0])); const result = Array.from(groups, ([group, values]) => ({group, values})); console.log(result);
You could build up a hashtavle to find duplicate descriptors:
const result = [], hash = {};
for(const [value, group] of abc) {
if(hash[group]) {
hash[group].push(value);
} else {
result.push({ group, value: (hash[group] = [value]), });
}
}
Approach with single reduce
var abc = [
['apple', 'fruit'],
['banana', 'fruit'],
['grapes', 'fruit'],
['red', 'color'],
['blue', 'color'],
['black', 'color']
]
var r = abc.reduce((prev, curr) => {
if(prev.findIndex(p => p.group === curr[1]) === -1) {
prev = prev.concat({group: curr[1], value: []})
}
let idx = prev.findIndex(p => p.group === curr[1])
prev[idx].value.push( curr[0] )
return prev;
}, [])
console.log(r)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.