1

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

2
  • 1
    Do you have particular need for the second output example? The array instead of an object? Without know your needs, the object makes the most sense. Commented Sep 18, 2022 at 8:04
  • 1
    1. Instantiate an output object. 2. Iterate the input array using forEach. 3. In the forEach function body, get the current subarray, and the first and second element of it and assign them to variables. 4. Assign the first element to a key in the output object, and 5. append the second element to an array that is the value of the key. Commented Sep 18, 2022 at 8:08

4 Answers 4

2

I'm sure we can find a couple of lodahs functions that will solve the problem together. But I think the easiest way to go about is a custom Array reducer.

const array = [[ 5, '103' ], [ 3, '104' ], [ 1, '105' ], [ 1, '106' ], [ 2, '107' ], [ 1, '108' ], [ 5, '109' ], [ 3, '110' ]];

const result = array.reduce((acc, [key, value]) => ({
    ...acc,
    [key]: [
        ...acc[key] || [],
        value,
    ]
}), {});

console.log(result)

Sign up to request clarification or add additional context in comments.

2 Comments

Nice answer. Destructure item to make it a bit more readable.
Thanks for the comment Ori, I did as you suggested
1

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>

Comments

0

If you need to group like objects, try this

function group(inarr){
  let outarr = inarr.reduce((r,a)=>{
    if(!r[a[0]]) r[a[0]] = [];
    r[a[0]].push(a[1])
    return r;
  }, {});
  console.log(outarr)
}

Comments

0

It can be done in vanillaJS by looping the array in forEach loop and for each cycle add the value to the object.

const toBeGrouped = [[ 5, '103' ], [ 3, '104' ], [ 1, '105' ], [ 1, '106' ], [ 2, '107' ], [ 1, '108' ], [ 5, '109' ], [ 3, '110' ]]

let grouped = {};
let k;
let value;
toBeGrouped.forEach((item) => {
  k = item[0];
  value = item[1];
  //check if the object key exists, then check is an array, then check if the current value is in the 
  if (grouped[k] && Array.isArray(grouped[k]) &&  !grouped[k].includes(value)) {
    grouped[k].push(value);
  } else {
    grouped[k] = [value];
  }
});
console.log(grouped)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.