I am trying to subtract two matrices, I have a function that takes in those matrices and returns a new matrix that has been subtracted. I get this error in node.js: TypeError: (intermediate value).map is not a function
subtract(a, b) { return new Matrix(a.rows, a.cols).map((_, i, j) => a.data[i][j] - b.data[i][j]); }
This is the function I use from my main file (note: I already have an instance of the class).
let m = new Matrix(2, 2); m.data[0] = [10, 11]; m.data[1] = [12, 13]; let n = new Matrix(2, 2); n.data[0] = [1, 2]; n.data[1] = [3, 4]; mat.subtract(m, n);
This is the class that I have created:
class Matrix { constructor(rows, cols) { this.rows = rows; this.cols = cols; this.index = 0; this.rowCount = 0; //this.matrixData = Array(this.rows).fill().map(() => Array(this.cols).fill(0)); this.data = Array(this.rows).fill().map(() => Array(this.cols).fill(0)); } }
Advertisement
Answer
I’m going to recommend a complete code rewrite that focuses on a plain functions instead of classes and methods. We begin writing our matrix
module below and will add an OOP-style interface in the second section of this post. –
// matrix.js const matrix = rows => ({ matrix, rows }) const empty = _ => matrix([]) const subtract = (t1, t2) => matrix(t1.rows.map((_, i) => subtractRow(t1.rows[i], t2.rows[i]))) const subtractRow = (r1, r2) => r1.map((v, i) => v - r2[i]) function toString (t) { const w = Math.max(...t.rows.flat().map(_ => String(_).length)) const s = t.rows.map(r => r.map(_ => String(_).padStart(w, " ")).join(" ")) return `[ ${s.join("n ")} ]` } export { empty, matrix, subtract, toString }
Next we write our main
module that uses the matrix
module –
// main.js import { matrix, subtract, toString } from "./matrix.js" const m1 = matrix([[10, 11], [12, 13]]) const m2 = matrix([[1,2], [3,4]]) console.log(toString(m1)) console.log(toString(m2)) console.log(toString(subtract(m1, m2)))
[ 10 11 12 13 ] [ 1 2 3 4 ] [ 9 9 9 9 ]
If you are more comfortable with an OOP-style interface, you we can add that to our matrix
module easily. Notice how our Matrix
class it is a simple wrapper around our existing plain functions –
// matrix.js (continued) class Matrix { constructor(t = empty()) { this.t = t } subtract(other) { return new Matrix(subtract(this.t, other.t)) } toString() { return toString(this.t) } static of(rows) { return new Matrix(matrix(rows)) } } export default Matrix
And here’s our main
module using our new Matrix
interface –
// main.js import Matrix from "./matrix.js" const m1 = Matrix.of([[10, 11], [12, 13]]) const m2 = Matrix.of([[1,2], [3,4]]) console.log(m1.toString()) console.log(m2.toString()) console.log(m1.subtract(m2).toString())
[ 10 11 12 13 ] [ 1 2 3 4 ] [ 9 9 9 9 ]
Chain for days, if you wish –
console.log(m1.subtract(m2).subtract(m2).toString()) console.log(m2.subtract(m1).subtract(m1).subtract(m1).toString())
[ 8 7 6 5 ] [ -29 -31 -33 -35 ]
As you can see we only write our matrix
module once and it is flexible enough to use in functional-style and OOP-style. To see this module technique used in another setting, see this answer where we build a linked list.
Wondering why we went through so much trouble in matrix.toString
? It’s so that the matrix can be nicely formatted even when element sizes differ –
import { matrix, toString } from "./matrix.js" const m3 = matrix([ [1,2,3], [11,22,33] [111,222,333] ]) console.log(toString(m3))
[ 1 2 3 11 22 33 111 222 333 ]