danem
danem

Reputation: 1515

Element-wise Operations In Javascript

I'm doing some physics simulations which of course involve vectors. This has become very difficult for me because to the best of my knowledge javascript doesn't support anything like this...

#with the aid of numpy
>>> a = np.array([1,2,3])
>>> b = np.array([9,2,7])
>>> a+b
array([10,  4, 10])

I've been able to work around this limitation by defining functions that will achieve the same thing, but my formulas end up looking like this:

add(x, add( mult(v,dt), mult(mult( a(x), .5), Math.pow(dt,2))))

So my question is whether there are better ways to achieve this functionality, whether they be features of the language I am unaware of, libraries that address this issue, or more effective ways to deal with it.

Thanks for the help all.

Upvotes: 28

Views: 28647

Answers (6)

Peopleware
Peopleware

Reputation: 1419

I like the answer of Varn K using map and extended it to handle an arbitrary number of arrays as input:

/**
 * @param {number[][]} arrays
 * @returns {number[]} Array as element-wise sum of the input arrays
 */
function addArrays(arrays) {
    return arrays.reduce((prev, curr) => prev.map((element, index) => element + curr[index]));
}

You might want to add checks for null and dimensions.

Upvotes: 0

Varn K
Varn K

Reputation: 400

we can use the map function to add array elements:

function addvector(a,b){
    return a.map((e,i) => e + b[i]);
}
addvector([2,3,4],[4,7,90]) # returns [6,10,94]

Upvotes: 22

verse
verse

Reputation: 236

Using zipWith from lodash (https://lodash.com/):

_.zipWith([1, 2, 3], [9, 2, 7], _.add);
// -> [10, 4, 10]

Upvotes: 5

J. Holmes
J. Holmes

Reputation: 18546

Check out Sylvester. I think it might be what you are looking for.

But if you wanted to implement the objects yourself, then it might be better to do a more OOP approach. JavaScript is a prototype-based language, so it different a little bit from other OOP languages, but its still pretty easy to implement your own prototypes.

Something like:

Vector = function(items) {
    this.items = items
}

Vector.prototype.add = function(other) {
    var result = []
    for(var i = 0; i < this.items; i++) {
        result.push( this.items[i] + other.items[i])
    }

    return new Vector(result);
}

Vector.prototype.subtract = function(other) { /* code to subtract */ }
Vector.prototype.multiply = function(other) { /* code to multiply */ }

And then use them like this:

var a = new Vector([1,2,3]);
var b = new Vector([5,0,1]);

var result = a.add(b)
result.items // [6,2,4]

Or if you wanted to, you could also extend the Array class with some functions with

Array.prototype.vectorAdd = function(other) { /* code to add another array as a vector */ };

And call that using

[1,2,3].vectorAdd([5,0,1])

Hopefully, that might give you a starting point to make your code a little more readable.

Just another note: Unfortunately in this case, JavaScript doesn't support operation overloading so you can't do neat stuff like a+b. You'll have to do something like a.add(b). but as long you return an appropriate object you can chain methods together. Like:

a.add(b).multiply(c).subtract(d);

ps. the presented code might be a little "off", I just typed it up off the top of my head, so treat it more like pseduocode :)

Upvotes: 16

user113716
user113716

Reputation: 322492

Don't know if this will help, but you can add methods to Array or Number by extending the constructor's .protoype object.

Example: http://jsfiddle.net/9JwLd/

Array.prototype.add = function( b ) {
    var a = this,
        c = [];
    if( Object.prototype.toString.call( b ) === '[object Array]' ) {
        if( a.length !== b.length ) {
            throw "Array lengths do not match.";
        } else {
            for( var i = 0; i < a.length; i++ ) {
                c[ i ] = a[ i ] + b[ i ];
            }
        }
    } else if( typeof b === 'number' ) {
        for( var i = 0; i < a.length; i++ ) {
            c[ i ] = a[ i ] + b;
        }
    }
    return c;
};
var a = [1,2,3];
var b = [9,2,7];

   // pass an Array
var c = a.add( b );  // [10,4,10]

   // pass a number
var d = a.add( 5 );  // [6,7,8]

The next version of JavaScript (ECMAScript) will likely include Array comprehensions, which may help as well. (Currently supported in SpiderMonkey.)

EXAMPLE: http://jsfiddle.net/dj6Eq/ (Test in newer versions of Firefox.)

var a = [1, 2, 3];
var b = [9, 2, 7];

var c = [a[n]+b[n] for (n in a) ];
var d = [a[n]+5 for (n in a) ];

EDIT: According to the proposal the syntax will be a little different than the current Mozilla implementation of Array comprehensions.

Upvotes: 5

Joseph Marikle
Joseph Marikle

Reputation: 78520

For just adding arrays in js, you can use this function

function addArrays(ar1, ar2){
    var ar3 = [];
    for(var i in ar1)
        ar3.push(ar1[i] + ar2[i]);
    return ar3;
}

and then call it like so

var array1 = [1,4,3];
var array2 = [5,3,2];
var array3 = addArrays(array1,array2);
// value of array3 is [6,7,5]

Upvotes: 3

Related Questions