Skip to content

neefrehman/make-matrix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

make-matrix

build npm version types included bundle size

A simple, type-safe way to create multi-dimensional arrays

Features

  • πŸ›Έ Easily create multi-dimensional arrays, with as many dimensions as needed
  • πŸŽ› Define exact dimensions to create an array of specified size
  • πŸ”’ Initialise every point in the array to a custom or self-aware starting value
  • πŸ“œ Comes with TypeScript definitions and type-safe returns
  • πŸ”¬ Tiny size, with no external dependencies

Installation

Install the package from NPM, and import it into your JavaScript or TypeScript file:

npm install make-matrix
import { makeMatrix } from "make-matrix";

Usage

Create a matrix

To create a matrix, pass in an array with the desired dimensions.

// create an array of size 3x3x2
const threeByThreeByTwoArray = makeMatrix([3, 3, 2]);

Initialise the matrix with set values

By default each point in the matrix will be initialised to null (so that if reading a point returns undefined, you know that it exists outside the current bounds of the matrix). To fill each point with a custom initial value, pass that value as the function's second parameter, initialValues:

// create a 3x5 array, with each point equal to 0
const twoDNumberArray = makeMatrix([3, 5], 0);

// create a 2x6x5 array, with each point equal to "value"
const threeDStringArray = makeMatrix([2, 6, 5], "value");

Pass a callback for dynamic initial values

The initialValues parameter can also be a callback, which you can use to dynamically create items for each position in the matrix. The callback can also accept an argument which will resolve to the current vector co-ordinates at each point in the matrix. This will allow you to populate your matrix in a "self-aware" fashion.

// create a 10x10x10 array, with each point a different random number between 0 and 9
const twoDRandomNumberArray = makeMatrix([10, 10, 10], () => Math.floor(Math.random() * 10));

// create a 5x5 array, with each point self-described by a string
const twoDVectorStringArray = makeMatrix([5, 5], (vector) => `I am at position ${vector.join()}`);

// create a 7x3x8 array, with each point transformed into a vector object
const twoDVectorObjectArray = makeMatrix([7, 3, 8], ([x, y, z]) => ({ x, y, z }));

With TypeScript

This package comes with type definitions to provide type-safety when working with the returned arrays.

Returned Matrices will be given a specific type dictated by T and the number of dimensions, where T is the type of the value passed to the functions initialValues parameter (or unknown, if not set).

For example, a three-dimensional array of numbers will be of type number[][][]. Points within the matrix can then only be reassigned to numbers. TypeScript's compiler will present errors when any reassignments are of the wrong type, including if they are at an incorrect depth in the array. This type-safety also occurs when callbacks are used to dynamically populate your matrix.

const threeDNumberArray = makeMatrix([2, 6, 5], 0); // return type of number[][][]

threeDNumberArray[2][1][2] = 10;      // βœ… OK

threeDNumberArray[2][1][2] = false;   // 🚨 error: Type 'boolean' is not assignable to type 'number'
threeDNumberArray[2][1] = 10;         // 🚨 error: Type 'number' is not assignable to type 'number[]'
threeDNumberArray[2][1][2][0] = 10;   // 🚨 error: Property '0' does not exist on type 'Number'

Please be aware that when using this function with a primitive instead of a literal typeβ€”such as when creating matrices of dynamic sizeβ€”the exact return type cannot be determined and will instead resolve to unknown[]. This ensures an array of at least one dimension is returned, but is unable to provide any more safety than that. You must type the resulting matrix yourself, if you are able to provide more information than the compiler can infer. If not, then an explicit return type of any[] will provide the most 'relaxed' typing experience.

const createDynamicMatrix = (dimensions: number[]) => makeMatrix(dimensions, 0); // return type of unknown[]

Example

To easily create a 3D grid using p5.js, make-matrix can be used like below. The source code for the grid at the top of this readme can be seen here, and an interactive demo of it here.

const res = 10; // 10px grid resolution
const matrix = makeMatrix([5, 5, 5]); // A 5x5x5 cube grid

for (let x = 0; x < matrix.length; x += res) {
  for (let y = 0; y < matrix[x].length; y += res) {
    for (let z = 0; z < matrix[x][y].length; z += res) {
      line(x, y, z, x + res, y, z);
      line(x, y, z, x, y + res, z);
      line(x, y, z, x, y, z + res);
    }
  }
}

Complexity

The makeMatrix algorithm is recursive and takes exponential time, or $O(2^n)$, to complete. This means that adding new dimensions dramatically increases the amount of time taken to create a matrix. While creating a matrix of 7 dimensions will happen in around a millisecond, doing the same with 10 dimensions will verge into the hundreds of milliseconds. Please bear this in mind when creating matrices.

API

makeMatrix<D, T>(
  dimensions: VectorOfLength<D>,
  initialValues?: T | ((vector: VectorOfLength<D>) => T) = null
): Matrix<D, T>;

Parameters

Name Description
dimensions The desired dimensions of the matrix. An array of numbers.
initialValues The value that each point in the matrix will initialise to. Can take any value. If a callback is passed, it will be run for each point in the matrix, which will be initialised to the callbacks returned value. (Optional β€” defaults to null).

Returns

Name Description
Matrix A multidimensional array of your desired dimensions, with each point initialised to equal the initialValues parameter (or its returned value).

Contributing

This project welcomes contributions. To get started, please open an issue to do discuss the change you'd like to make. Then fork the repo, open it in your editor, and run pnpm install in your terminal. This will get everything set up for you to start making changes.

Testing, linting and commit style

This project uses Biome, commitlint and vitest β€” in combination with lint-staged and simple-git-hooks β€” to enforce code quality, consistency and changelog style. These tools will check changed files, and cancel a commit with logging if any of the following are true:

  1. Biome has found non-fixable issues in the code
  2. The Vitest testing suites haven't all passed
  3. The commit message doesn't meet the conventional commit format (run pnpm run commitizen in terminal for help formatting your commit message)

Open your git logs to debug commit errors.

License

This package is MIT Licensed.