Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding arrays to an array of arrays

I'm sure this is super simple, and I don't really want a complete solution, but pointing in the right direction as I'm learning.

I have:

let randomArray = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];

and the goal is to make it look like this, grouping like items:

[[1,1,1,1],[2,2,2],[10],[20,20],[391],[392],[591]]

My following code arranges, and groups fine. I push the temp to my Group array. But when I reset my "tempArray" to make it empty ready for the next "group", it removes the data from my group as well. Because it's linked? I assume? Maybe?

The only thing left at the end is the last item.

How do I stop it doing this?

    // My SOlution
let randomArray = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];
let tempArray = [];
let groupArray = [];

function cleanTheRoom (arr) {
    let ascendingArray = arr.sort(function(a,b) {
        return a - b;
    });
    tempArray.push(randomArray[0])
    for (let i = 1; i <= randomArray.length; i++) {
        if (randomArray[i] === tempArray[0]) {
            tempArray.push(randomArray[i])
        } else {
            groupArray.push(tempArray);
            tempArray = []
            tempArray.push(randomArray[i])
        }
    } console.log(groupArray)
}

cleanTheRoom(randomArray);
like image 562
Voodoo Science Avatar asked Sep 04 '20 15:09

Voodoo Science


People also ask

How do you add one array to another array?

Use the concat function, like so: var arrayA = [1, 2]; var arrayB = [3, 4]; var newArray = arrayA. concat(arrayB); The value of newArray will be [1, 2, 3, 4] ( arrayA and arrayB remain unchanged; concat creates and returns a new array for the result).

How do you add two arrays together?

The concat() method concatenates (joins) two or more arrays. The concat() method returns a new array, containing the joined arrays. The concat() method does not change the existing arrays.

How do I merge an array of arrays into a single array?

concat() The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.


3 Answers

I took your code and changed some parts.

  • Array#sort sorts in place. No need to assign to a new variable.

  • Iterate from zero and have a look to the data directly, by using the value at index minus one and at the index. If unequal, a new group is found. In this case just assign an empty array to groupArray and push the group to the result.

    Instead of using the same object reference and just empty the array by assigning zero to length, this approach takes a new array.

  • Push the value outside of the if statement, because it was doubled in then and else part.

  • Finally return the array with the groups.

function cleanTheRoom(array) {
    let result = [];
    let groupArray;

    array.sort(function(a, b) {
        return a - b;
    });

    for (let i = 0; i < array.length; i++) {
        if (array[i - 1] !== array[i]) {
            groupArray = [];
            result.push(groupArray);
        }
        groupArray.push(array[i]);
    }

    return result;
}

let randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

console.log(cleanTheRoom(randomArray));
like image 196
Nina Scholz Avatar answered Oct 22 '22 16:10

Nina Scholz


There are three main problems in your code:

  1. You are using randomArray inside the function but you should be using ascendingArray

  2. tempArray.length = 0 - this statement mutates the original tempArray and since you are pushing the tempArray array in the groupArray, changes to tempArray are reflected in the groupArray as well.

    You could clone the tempArray and push the copy of the tempArray in the groupArray

    groupArray.push([...tempArray]);
    

    or you could assign the new empty array to tempArray

    tempArray = [];
    
  3. When its the last iteration of the loop, you are not pushing the contents of the tempArray in the groupArray. This will lead to the groupArray not containing the last number in the sorted array, i.e. 591. You need to check if the current iteration is the last iteration of the loop or not. If it is, push the tempArray in the groupArray

    for (let i = 1; i < ascendingArray.length; i++) {
      ...
    
      if (i == ascendingArray.length - 1) {
        groupArray.push(tempArray);
      } 
    } 
    

Here's a simplified version of your code:

let randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

function cleanTheRoom(arr) {
  let tempArray = [];
  let groupArray = [];

  let ascendingArray = arr.sort(function (a, b) {
    return a - b;
  });

  for (let i = 0; i < ascendingArray.length; i++) {
    tempArray.push(ascendingArray[i]);

    if (ascendingArray[i + 1] !== ascendingArray[i]) {
      groupArray.push(tempArray);
      tempArray = [];
    }
  }

  console.log(groupArray);
}

cleanTheRoom(randomArray);
like image 40
Yousaf Avatar answered Oct 22 '22 16:10

Yousaf


There might be even faster approaches but I took a quick shot at it:

  • first, we break down the array into the groups
  • and then we sort not on the whole array but only on the group's key to avoid a second full iteration over the array.

I've used a Map instead of a dictionary for the groups because we can leverage the Map.set function neatly. It returns the whole Map which we need as the return value within the reduce.

const randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const isGroup = (acc, number) => Array.isArray(acc.get(number));
const setGroup = (acc, number) => acc.set(number, isGroup(acc, number) ? acc.get(number).concat([number]) : [number]);
const unorderedNumberGroups = randomArray.reduce(setGroup, new Map());
const order = [...unorderedNumberGroups.keys()].sort((a, b) => a - b);
const orderedNumberGroups = order.reduce((acc, key) => acc.concat([unorderedNumberGroups.get(key)]), []);
console.log(orderedNumberGroups);

Here you go with a more debuggable version so you can try to understand the version above:

const randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const isGroup = (acc, number) => Array.isArray(acc.get(number));
const unorderedNumberGroups = randomArray.reduce((acc, number) => {
  if (isGroup(acc, number)) {
    const mapEntry = acc.get(number);
    const newEntry = mapEntry.concat([number]);
    return acc.set(number, newEntry); // we need to return the acc, the Map.set method returns the whole Map
  } else {
    return acc.set(number, [number]); // we need to return the acc, the Map.set method returns the whole Map
  }
}, new Map()); // initialize the accumulator we an empty Map
const keysAsArray = [...unorderedNumberGroups.keys()];
const order = keysAsArray.sort((a, b) => a - b);
const orderedNumberGroups = order.reduce((acc, key) => {
  const arrayForTheKey = unorderedNumberGroups.get(key);
  return acc.concat([arrayForTheKey]); // note the breakets!

  // equivalent code:
  // acc.push(arrayForTheKey);
  // return acc;
}, []); // initialize the accumulator with an empty Array
console.log(orderedNumberGroups);
like image 35
Robin F. Avatar answered Oct 22 '22 15:10

Robin F.