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.

2
  • Split array into chunks? Commented Jul 15, 2021 at 20:35
  • Can a chunk have both one A and one B? What would happen then? Commented Jul 15, 2021 at 20:55

3 Answers 3

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))

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

2 Comments

@MikeM Thanks for asking that. I've updated my answer, it should work now.
Yes, seems to work, but you're not likely to get many votes as it doesn't use reduce.
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)

Comments

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)

1 Comment

Not quite the right shape: the second array element contains three objects.

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.