Home > Mobile >  Why does pushing values into array result in an 'undefined' error?
Why does pushing values into array result in an 'undefined' error?

Time:08-27

I am currently working on a sorting visualizer project to try and better understand JavaScript.

My issue is that I am calling 'push' on this array, and am getting the error

Cannot read properties of undefined (reading 'push')

After trying to research this problem, I understand that it means that the thing I am trying to reference with push is undefined, but I am failing to understand why this is the case.

Due to my lack of understanding, I cannot post a smaller sequence of code.

This is what my code does:

  • I run some sorting algorithms.
  • I output array columns to the screen that get visually sorted.

The end goal will be similar to this video. For my algorithm functions, I have a separate "animations" array that starts off as empty and then gets filled with pairs of array indices and colors.

After finishing the algorithm, I end up with this "animations" array that tells me how to manipulate the array on the screen to get it sorted.

Below is a part of my program, in which I am trying to implement heapsort.

export function getHeapSortAnimations(array) {

    const animations = [];
    if (array.length <= 1) { return array; }
    heapSortHelper (array, animations);
    return animations;

  }

    function heapSortHelper(array, animations) {
    
        let len = array.length;

            for (let i = Math.floor(len / 2) - 1; i >= 0; i--){
                heapify(array, len, i, animations);
            }

            for (let i = len - 1; i > 0; i--) {
            
                let temp = array[0];
                array[0] = array[i];
                array[i] = temp;

                heapify(array, i, 0, animations);
            }

    }

    
    function heapify(array, size, i, animations){

        let max = i;
        let right = rightChildIndex(i);
        let left = leftChildIndex(i);

        if (left < size && array[left] > array[max]) { 
            animations.push([0, 'red']);
            max = left;     
        }
        if (right < size && array[right] > array[max]) { 
            max = right; 
        }

        if (max != i) { 
            let temp = array[i];
            array[i] = array[max];
            array[max] = temp; 
            heapify(array, size, max);
        }
    
        
    }

    function parentIndex(index){ return Math.floor((index-1)/2); }

    function leftChildIndex(index){ return (2 * index   1); }

    function rightChildIndex(index){ return (2 * index   2); }

Note: In the first if statement of the "heapify" function, I am passing the index 0 along with the color 'red', which doesn't really make sense in regards to the algorithm; basically, anywhere I try to push something into my animations array I get:

Cannot read properties of undefined (reading 'push')"

The main reason this is so confusing is that I have a separate "Quicksort" file (code below), where I use this animations array. Here, I push values into it all over the place, without getting an error:

export function getQuickSortAnimations (array) {
    const animations = [];

    if (array.length <= 1) { return array; }

    console.log("unsorted array: "   array);

    quickSort(array, 0, array.length-1, animations);

    console.log("animations: "   animations);
    console.log("sorted array: "   array);

    return animations;
}

function quickSort (array, lowIndex, highIndex, animations){

    if (lowIndex >= highIndex) { 
        animations.push([lowIndex, 'purple']);
        return; 
    }

    let pivot = array[highIndex];
    
    let leftPtr = partition(array, lowIndex, highIndex, pivot, animations);

        quickSort(array, lowIndex, leftPtr-1, animations);
        quickSort (array, leftPtr 1, highIndex, animations);

}


function partition (array, lowIndex, highIndex, pivot, animations){

    let leftPtr = lowIndex;
    let rightPtr = highIndex-1;

    // Coloring our first instance of leftPtr and our Pivot(highIndex)
    animations.push([highIndex, 'yellow']);
    animations.push([leftPtr, 'red']);
    animations.push([rightPtr, 'red']);

    

        while (leftPtr < rightPtr) {
            while ((array[leftPtr] <= pivot) && (leftPtr < rightPtr)){
                // Send rightPtr to animations once to decolor
                animations.push([leftPtr, 'turquoise']);
                leftPtr  ;
                // Send new leftPtr to animations to color new array bar
                animations.push([leftPtr, 'red']);
            }
            while ((array[rightPtr] >= pivot) && (leftPtr < rightPtr)){
                // Send rightPtr to animations once to decolor
                animations.push([rightPtr, 'turquoise']);
                rightPtr--;
                // Send new rightPtr to animations to color new array bar
                animations.push([rightPtr, 'red']);
            }
            // temp variable holds the value of our leftPtr index while we perform swap
            let temp = array[leftPtr];
            // swap our leftPtr with our rightPtr in animations
            animations.push([leftPtr, array[rightPtr]]);
            // swap our rightPtr with our leftPtr in animations using temp
            animations.push([rightPtr, temp]);
            // same swap as above but with the our actual array
            [array[leftPtr], array[rightPtr]] = [array[rightPtr], array[leftPtr]];
        }
        animations.push([highIndex, 'turquoise']);

        if (array[leftPtr] > array[highIndex]) {
            // temp variable holds the value of our leftPtr index while we perform swap
            let temp = array[leftPtr];
            // swap our leftPtr with our highIndex in animations
            animations.push([leftPtr, array[highIndex]]);
            // swap our highIndex with our leftPtr in animations using temp
            animations.push([highIndex, temp]);
            // same swap as above but with the our actual array
            [array[leftPtr], array[highIndex]] = [array[highIndex], array[leftPtr]];
            animations.push([leftPtr, 'purple']);
        }
        else {
            leftPtr = highIndex;
            animations.push([leftPtr, 'purple']);
        }


        
        
        return leftPtr;


}

I just don't understand why I can push values into this array in one file, but then in another file that is very similar, I can't seem to push any values into the array at all.

CodePudding user response:

The error you got is due to your heapify function. It expects 4 parameters, the last one is your animation array, but inside of this function you called itself recursive with 3 parameters only. So you are writing to animation array but not every time, due to sometimes it is undefined. I added a console log and a comment in your code to show the issue.

function getHeapSortAnimations(array) {
  const animations = [];
  if (array.length <= 1) {
    return array;
  }
  heapSortHelper(array, animations);
  return animations;
}
function heapSortHelper(array, animations) {
  let len = array.length;
  for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
    heapify(array, len, i, animations);
  }
  for (let i = len - 1; i > 0; i--) {
    let temp = array[0];
    array[0] = array[i];
    array[i] = temp;
    heapify(array, i, 0, animations);
  }
}
function heapify(array, size, i, animations) {
  console.log(JSON.stringify(animations));
  let max = i;
  let right = rightChildIndex(i);
  let left = leftChildIndex(i);
  if (left < size && array[left] > array[max]) {
    animations.push([0, "red"]);
    max = left;
  }
  if (right < size && array[right] > array[max]) {
    max = right;
  }
  if (max != i) {
    let temp = array[i];
    array[i] = array[max];
    array[max] = temp;
    // Here: heapify function expects 4 parameters. 3 only.
    heapify(array, size, max);
  }
}
function leftChildIndex(index) {
  return 2 * index   1;
}
function rightChildIndex(index) {
  return 2 * index   2;
}
const data = [4, 2, 8, 5, 6, 1];
try {
  const animations = getHeapSortAnimations(data);
  console.log(JSON.stringify(animations));
} catch (e) {
  console.error(e);
}

  • Related