Yanic
Yanic

Reputation: 133

Find most similar array of numbers

Let's say I have two arrays:

a=[168, 76, 62, 86]

b=[168, 80, 65, 90]

My input

[166.5, 75.5, 62, 86]

Now I want to get array "a" as my "result" because it is more similar to "a" than it is to "b".

How can I do that?

Upvotes: 1

Views: 1130

Answers (3)

vassiliskrikonis
vassiliskrikonis

Reputation: 596

Let's say that you've got two number arrays

x = [x1, x2, ..., xn]

y = [y1, y2, ..., yn]

The difference (i.e inverse similarity) between them is calculated by passing them through some error function E let's say

E = Σ (xi - yi)2

it's the same as calculating:

(x1 - y2)2 + ... + (xn - yn)2

= Σx2 + Σy2 - Σ(2xiyi)

= Σxi2 + Σyi2 - 2ΣxiΣyi

which means we can now use just the built-in Javascript methods .map() and .reduce().

const toSquare(ar) = ar.map( v => v*v )
const sum(ar) = ar.reduce( (acc, v) => acc + v )

function error(ar1, ar2) {
  return sum(toSquare(ar1)) + sum(toSquare(ar2)) + 2*sum(ar1)*sum(ar2)
}

Much simpler:

you can also use underscore's or lodash's .zip function:

function error(ar1, ar2) {
    return _.zip([ar1, ar2]).map( pair => Math.pow(p[0]-p[1], 2) ).reduce( (acc, v) => acc + v )
}

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386654

You could collect the absolute deltas and choose the one with the smaller error.

var array1 = [168, 76, 62, 86],
    array2 = [168, 80, 65, 90],
    input = [166.5, 75.5, 62, 86],
    error = [array1, array2].map(function (a) {
        return input.reduce(function (r, b, i) {
            return r + Math.abs(a[i] -b);
        }, 0);
    });
  
console.log(error); // [2, 13] take the first one with smaller error.

Upvotes: 5

DarkMukke
DarkMukke

Reputation: 2489

You will have to create a manual function to do that. There is no built in way to do so.

function closest( inputArray, controlArrays) {

    var margins;
    for(var i=0, iMax=controlArrays.length; i < iMax; i++ ){
        margins[i] = 0;
        for(var j=0, jMax=inputArray.length; j < jMax; j++) {
            //get the difference between the numbers and add it for the margins for that control array
            margins[i] += Math.abs(inputArray[j]-controlArrays[j][i]);
        }
    }
    //find smallest margin
    var index = 0;
    var value = margins[0];
    for (var m = 1, mMax = temp.length; m < mMax; m++) {
        if (temp[m] < value) {
            value = temp[m];
            index = m;
        }
    }
    //return the smalles margin;
    return controlArrays[index];
}

Upvotes: 1

Related Questions