1

In the below function I am attempting to get an output which resembles this:

[[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591].

I can see that the problem I have embedded is that I am always adding the temp array with a push to the functions return, as a result, all of the individual numbers apart from the last number in the for each function are being pushed into the target array with the array object also.

I feel as though I need a further conditonal check but for the life of me I am unable to come up with solution which works.

Any suggestions would be much appreciated.

const sortme = (unsortedArr)=> {

let tempArr = []; 

let outputArr = []; 

const reorderedArr = unsortedArr.sort((a,b) => a-b); 

reorderedArr.forEach((number, i) => {

    if ((i === 0) || (reorderedArr[i] === reorderedArr[i-1])) {
    tempArr.push(number);  
    }

    else {     
    outputArr.push(tempArr);
    tempArr = [];
    tempArr.push(number); 
}  
})

outputArr.push(tempArr[0]);
    return outputArr; 
}

const unsortedArr = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20]; 

sortme(unsortedArr); 

4 Answers 4

2

i would make a deduped copy and .map() it to transform the values into arrays containing values from the original ( sorted ) array that you get using a .forEach :

const unsortedArr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

const sortMe = (arr) => {
  arr = arr.sort((a, b) => a - b);
  
  // a short way to dedupe an array
  // results in : 1, 2, 4, 5, 10, 20, 391, 392, 591
  let dedupe = [...new Set(arr)]; 
  let tmpArr;

  return dedupe.map(e => {
    tmpArr = []; // empty tmpArr on each iteration
    
    // for each element of the deduped array, look for matching elements in the original one and push them in the tmpArr
    arr.forEach(a => {
      if (a === e) 
        tmpArr.push(e);
    })
    
    if(tmpArr.length === 1)
      return tmpArr[0]; // in case you have [4] , just return the 4
    else
      return tmpArr; // in case you have [1,1,1,1]
    
    // shorthand for the if/else above
    // return tmpArr.length === 1 ? tmpArr[0] : tmpArr;
  });
}

const result = sortMe(unsortedArr);

console.log(result);

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

3 Comments

This seems cool, I am struggling to understand exactly how this operates but I will look into it futher, map was ideally what I had in mind to use however your solution is beatifully confusing to me noob eyes :D. Thankyou!
@SimonDean thank you, i will add comments in the code
This is acutally super helpful! I did make my own solution, but i can see I need to practice the higher order functions as they make everything so much shorter!
1

This should work (using reduce):

 
const unsortedArr = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];

let lastValue = null;
var newArr = unsortedArr.sort((a,b) => a-b).reduce((acc, value) => {

    if (acc.length == 0 || ((acc.length > 0 || !acc[acc.length-1].length) && lastValue !== value)) {
        acc.push(value);
    } else if (acc.length > 0 && lastValue === value) {
        acc[acc.length-1] = (acc[acc.length-1].length ? acc[acc.length-1].concat([value]): [value, value]);
    } 
    
    lastValue = value;
    return acc;
}, []);


console.log(newArr);

2 Comments

4 ifs , i usually use switch/case when i have more than 2
Oh yeah, I'd actually streamline the logic within the reduce proc. I'd cut this down a little with a bit of work :)
0

And another approach, just for fun:

const unsortedArr = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];

var arr = unsortedArr.sort((a,b) => a-b).reduce((acc, value) => {
    if (acc.length > 0 && acc[acc.length-1].includes(value)) {
        acc[acc.length-1].push(value);
    } else {
        acc.push([value])
    }
    return acc;
}, []).map((v) => v.length > 1 ? v: v[0]);

console.log(arr);

Comments

0

I hope the below one is quite simple;

function findSame(pos, sortedArr){
    for(let i =pos; i<sortedArr.length; i++){
        if(sortedArr[i] !== sortedArr[pos]){
            return i
        }
    }
}

function clubSameNumbers(unsortedArr){
    let sortedArr = unsortedArr.sort((a,b)=>a-b) 
    //[ 1, 1, 1, 1, 2, 2, 2, 4, 5, 10, 20, 20, 391, 392, 591 ]
    let result = [] 
    for(let i = 0; i < sortedArr.length; i = end){
        let start = i
        var end = findSame(i, sortedArr)
        let arr = sortedArr.slice(i, end)
        arr.length > 1 ? result.push(arr) : result.push(...arr)         
    }
    return result
}


console.log(clubSameNumbers([1,2,4,591,392,391,2,5,10,2,1,1,1,20,20]))
//[ [ 1, 1, 1, 1 ], [ 2, 2, 2 ], 4, 5, 10, [ 20, 20 ], 391, 392, 591 ]

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.