2

I have an array of objects and I want to be able to sort them by their "site" value into pairs. There can't be more that 2 objects in each child array so if there is 3 matches I get 1 child array with 2 objects and 1 child array with 1 object.

I have:

[{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];

I want:

[[{site:'A'}, {site:'A'}],[{site:'B'}, {site:'B'}], [{site:'B'}]] 

Whats the best way to do this? any help is appreciated.

AbsoluteBeginner
  • 2,160
  • 3
  • 11
  • 21
Neatpixels
  • 75
  • 1
  • 9

3 Answers3

3

This should work for you

function sortArray(arr){
    arr.sort((a,b)=>a.site > b.site ? 1 : -1) // Sorting the array to have consecutive values
    let chunks = [];
    for(let i = 0;i<arr.length;i+=2){
        if(arr[i]?.site == arr[i+1]?.site) chunks.push(arr.slice(i,i+2));
         else {
               chunks.push([arr[i]]);
               i--;
         }
    }
    return chunks;
}

let arr = [{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];
console.log(sortArray(arr))
trizin
  • 347
  • 2
  • 13
2

Using reduce ;) :

const a = [{
  site: 'A'
}, {
  site: 'A'
}, {
  site: 'B'
}, {
  site: 'B'
}, {
  site: 'B'
}];

var r = a.reduce((ac, x) => ({
  ...ac,
  [x.site]: [...(ac[x.site] || []), x]
}), {})

var r2 = Object.values(r).flatMap(x =>
  x.reduce((ac, z, i) => {
    if (i % 2) {
      ac[i - 1].push(z)
      return ac
    }
    return [...ac, [z]]
  }, []))


console.log(r2)

PS: Since this is hard to read I'd suggest to use lodash (specifically groupBy and chunk methods)

maioman
  • 18,154
  • 4
  • 36
  • 42
0

It's kind of a 'groupBy' operation (as seen in underscore or lodash). Those produce an object keyed by the values being grouped. Consider writing it that way for general use. To get the shape the OP is looking for, strip out the values of that result...

function groupBy(array, key) {
  return array.reduce((acc, el) => {
    let value = el[key];
    if (!acc[value]) acc[value] = [];
    acc[value].push(el);
    return acc;
  }, {});
}

let array = [{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];
let grouped = groupBy(array, 'site');  // produces { A: [{site:'A'} ...], B: ... }
let groups = Object.values(grouped)
console.log(groups)
danh
  • 62,181
  • 10
  • 95
  • 136