Does anyone know how to group nested arrays in Javascript like this? (can be vanilla or lodash method) (I work on Reactjs)
from
[[ 5, '103' ], [ 3, '104' ], [ 1, '105' ], [ 1, '106' ], [ 2, '107' ], [ 1, '108' ], [ 5, '109' ], [ 3, '110' ]]
to
{5: ['103','109'], 3: ['104','110'], 2: ['107'], 1: ['105','106','108']}
or
[[5, ['103','109']], [3, ['104','110']], [2, ['107']], [1, ['105','106','108']]]
Thank you
Use _.groupBy()
the _.head()
(the 1st element of the array), and then map the values and extract the last parameter from each of the sub-arrays in the group.
Note: since we're grouping the array into an object, and the keys are integers, the order of the keys would be numeric ascending.
const { mapValues, groupBy, head, map, last } = _;
const array = [[ 5, '103' ], [ 3, '104' ], [ 1, '105' ], [ 1, '106' ], [ 2, '107' ], [ 1, '108' ], [ 5, '109' ], [ 3, '110' ]];
const result = mapValues(
groupBy(array, head),
arr => map(arr, last)
);
console.log(result);
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Without lodash you can reduce the array to a Map
, and then convert the Map's to an array using Array.from()
or to an object using Object.fromEntries()
.
Note: A Map preserves the order of insertion, even for integer keys, and converting the Map to an array of arrays would also maintain the original order.
const array = [[ 5, '103' ], [ 3, '104' ], [ 1, '105' ], [ 1, '106' ], [ 2, '107' ], [ 1, '108' ], [ 5, '109' ], [ 3, '110' ]];
const map = array.reduce((acc, [key, val]) => {
if(!acc.has(key)) acc.set(key, []);
acc.get(key).push(val);
return acc;
}, new Map());
console.log(Array.from(map)); // convert the Map to an array
console.log(Object.fromEntries(map)) // convert the Map to an object
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>