JavaScript Array Manipulations

practicing_datscy

Practicing Datscy

Posted on August 31, 2024

JavaScript Array Manipulations

Manipulating 2d, 3d, or 4d arrays in JavaScript are necessary for AI model training and data pre-processing analysis (text/image/audio/video).

Below are a few useful functions for array manipulation using pure JavaScript without matrix packages like Tensorflow.js.

Transpose of a 2d array

function transpose_2d_array(arr) {

    var transpose_colNum = arr.length;
    var transpose_rowNum = arr.at(0).length;
    var transpose_arr = [];
    for (var i=0; i<transpose_rowNum ; i++) {
        const col = Array.from({ length: transpose_colNum }, (_, i) => 0);
        transpose_arr.push(col);
    }

    for (var i=0; i<arr.length; i++) {
        for (var j=0; j<arr.at(i).length; j++) {
            transpose_arr[j][i] = arr[i][j];
        }
    }
    return transpose_arr;
}
Enter fullscreen mode Exit fullscreen mode

Print the Shape of an array

async function recur_func(arr) {
    if (arr != undefined) {
        return [arr[0], arr.length];
    } else {
        return arr;
    }
}

async function shape(arr) {
    var out = await recur_func(arr);
    var shap = [out[1]];
    var c = 0; // typically work with 4D arrays or less
    while (out != undefined && c < 4) {
        out = await recur_func(out[0]);
        if (out != undefined) {
            shap.push(out[1]);
        }
        c = c + 1;
    }
    return shap.slice(0, shap.length-1);
}
Enter fullscreen mode Exit fullscreen mode

Exchange dimensions of an array

The tensorflow.js library and other numerical libraries have a reshape function, however, it is uncertain which dimensions maybe exchanged if two or more dimensions have the same size number. For example, reshaping a [2,1,2] into a [1,2,2] does not specify if the 0th dimension should be switch to the 1st or the 2nd dimension. In the function below, one can specify exactly which size should correspond with a particular dimension.

async function exchange_3d_dimensions(arr_3d, output_dims_index) {

    // output_dims_index: [0,2,1] implying how to switch the dimension index of arr_3d, this is technically more precise because two dimension indexes could have the same size. So one is specifying exactly which dimension index to use for a particular dimension.

    // output_dims_index specifies the [dimension index] of the desired output array 
    // [2,2,1] = [org_0th_dim, org_1st_dim, org_2nd_dim] => [2,1,2] = [org_0th_dim, org_2nd_dim, org_1st_dim] = [0,2,1] 

    // [0] List the original array location_values and values
    var org_0th_dim = [];
    var org_1st_dim = [];
    var org_2nd_dim = [];
    var val = [];

    for (var i=0; i<arr_3d.length; i++) {
        for (var j=0; j<arr_3d[0].length; j++) {
            for (var k=0; k<arr_3d[0][0].length; k++) {
                   org_0th_dim.push(i);
                   org_1st_dim.push(j);
                   org_2nd_dim.push(k);
                   val.push(arr_3d[i][j][k])
            }
        }
    }

    // Need to transform output_dims_index, from index to dimensions
    var dims_of_org_arr = [arr_3d.length, arr_3d[0].length, arr_3d[0][0].length];
    var dims = output_dims_index.map((val, i) => { return dims_of_org_arr.at(val); });


    // [1] Make the new shape array, filled with zeros
    var desired_3d = await zeros(dims);

    // Exchange notation for desired output index dimensions
    var all = [org_0th_dim, org_1st_dim, org_2nd_dim];
    var all_switched = output_dims_index.map((val, i) => { return all.at(val); });
    org_0th_dim = all_switched.at(0);
    org_1st_dim = all_switched.at(1);
    org_2nd_dim = all_switched.at(2);


    // [2] Fill in output shaped 3d array
    var desired_0th_dim = dims.at(0);
    var desired_1st_dim = dims.at(1);
    var desired_2nd_dim = dims.at(2);

    for (var i=0; i<desired_0th_dim; i++) {
        for (var j=0; j<desired_1st_dim; j++) {
            for (var k=0; k<desired_2nd_dim; k++) {

                // cycle over the index of a for every i,j,k value
                   for (var ind=0; ind<org_0th_dim.length; ind++) {
                       if (org_0th_dim.at(ind) == i && org_1st_dim.at(ind) == j && org_2nd_dim.at(ind) == k) {
                        desired_3d[i][j][k] = val.at(ind);
                       }
                   }
            }
        }
    }

    return desired_3d;       
}

// -----------------------------------------------

async function zeros(dims) {

    // dims: [desired_0th_dim, desired_1st_dim, desired_2nd_dim]

    var out = [];

    if (dims.length == 1) {
        var desired_0th_dim = dims.at(0);

        out = Array.from({length: desired_0th_dim}, (val, ind) => { return 0; }); 

    } else if (dims.length == 2) {
        var desired_0th_dim = dims.at(0);
        var desired_1st_dim = dims.at(1);

        for (var i=0; i<desired_0th_dim; i++) {
            var arr = Array.from({length: desired_1st_dim}, (val, ind) => { return 0; }); 
            out.push(arr);
        }

    } else if (dims.length == 3) {
        var desired_0th_dim = dims.at(0);
        var desired_1st_dim = dims.at(1);
        var desired_2nd_dim = dims.at(2);

        for (var i=0; i<desired_0th_dim; i++) {
            temp = [];
            for (var j=0; j<desired_1st_dim; j++) {
                var arr = Array.from({length: desired_2nd_dim}, (val, ind) => { return 0; }); 
                temp.push(arr);
            }
            out.push(temp);
        }

    } else {
        console.log('Enter an array of length 1, 2, or 3. (ie: [desired_0th_dim, desired_1st_dim, desired_2nd_dim])')
    }

    return out;
}
Enter fullscreen mode Exit fullscreen mode

I hope these array utility functions will be helpful to someone.

Happy Practicing! šŸ‘‹

šŸ’» GitHub | šŸŒ· Practicing Datscy @ Dev.to | šŸŒ³ Practicing Datscy @ Medium

References

  1. Inspiration for the creation of array functions: https://js.tensorflow.org/api/latest/
šŸ’– šŸ’Ŗ šŸ™… šŸš©
practicing_datscy
Practicing Datscy

Posted on August 31, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

JavaScript Array Manipulations
javascript JavaScript Array Manipulations

August 31, 2024