Shakti Patel
Shakti Patel

Reputation: 3862

Compare Javascript array object and return closest pair

Array 1

[{
  "index": 3,
  "ratio": 1.9310344827586208
}, {
  "index": 0,
  "ratio": 2.4122497055359244
}, {
  "index": 2,
  "ratio": 2.5
}, {
  "index": 1,
  "ratio": 1
}]

Array 2

[{
"index": 0,
  "ratio": 0.6670000000000006
}, {
  "index": 2,
  "ratio": 1
}, {
  "index": 3,
  "ratio": 1
}, {
  "index": 1,
  "ratio": 2.409638554216892
}]

I want result like

From Array 1 ratio "2.4122497055359244" and Array 2 ration"2.409638554216892" is closest pair

[{array1: 0, array2:1}, {array1: 1, array2:2}, ....]

Upvotes: 0

Views: 97

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386680

You could iterate the first array and take from the second array the smallest deltas. If more than one item is the smallest, both items are included in the result set.

The result is sorted by the closest items.

function delta(a, b) {
    return Math.abs(a - b);
}

var array1 = [{ index: 3, ratio: 1.9310344827586208 }, { index: 0, ratio: 2.4122497055359244 }, { index: 2, ratio: 2.5 }, { index: 1, ratio: 1 }],
    array2 = [{ index: 0, ratio: 0.6670000000000006 }, { index: 2, ratio: 1 }, { index: 3, ratio: 1 }, { index: 1, ratio: 2.409638554216892 }],
    result = array1
        .reduce((r, a) => r.concat(array2.reduce((s, b) => {
            var d1 = s && delta(a.ratio, b.ratio),
                d2 = s && delta(a.ratio, s[0].b.ratio);

            if (!s || d1 < d2) {
                return [{ delta: delta(a.ratio, b.ratio), a, b }];
            }
            if (d1 === d2) {
                s.push({ delta: delta(a.ratio, b.ratio), a, b });
            }
            return s;
        }, undefined)), [])
        .sort((a, b) => a.delta - b.delta)
        .map(({ a: { index: array1 }, b: { index: array2 } }) => ({ array1, array2 }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Just take the first smallest delta.

function delta(a, b) {
    return Math.abs(a - b);
}

var array1 = [{ index: 3, ratio: 1.9310344827586208 }, { index: 0, ratio: 2.4122497055359244 }, { index: 2, ratio: 2.5 }, { index: 1, ratio: 1 }],
    array2 = [{ index: 0, ratio: 0.6670000000000006 }, { index: 2, ratio: 1 }, { index: 3, ratio: 1 }, { index: 1, ratio: 2.409638554216892 }],
    result = array1
        .reduce((r, a) => r.concat(array2.reduce((s, b) => {
            var d1 = s && delta(a.ratio, b.ratio),
                d2 = s && delta(a.ratio, s[0].b.ratio);

            return !s || d1 < d2
                ? [{ delta: delta(a.ratio, b.ratio), a, b }]
                : s;
        }, undefined)), [])
        .sort((a, b) => a.delta - b.delta)
        .map(({ a: { index: array1 }, b: { index: array2 } }) => ({ array1, array2 }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Shakti Patel
Shakti Patel

Reputation: 3862

function findNearestRatio(item,array){
    var val = array.reduce((acc,curr)=>{
      var difference = Math.abs(curr.ratio-item.ratio);
      return difference<acc.diff?{diff:difference,item:curr}:acc;
    },{diff:1000});
    return val;
}

var sortFunc = (a,b) => {
  if(a.difference<b.difference){
    return -1;
  }else if(a.difference>b.difference){
    return 1;
  }else{
    return 0;
  }
};

var array1 = [{ index: 3, ratio: 1.9310344827586208 }, { index: 0, ratio: 2.4122497055359244 }, { index: 2, ratio: 2.5 }, { index: 1, ratio: 1 }],
array2 = [{ index: 0, ratio: 0.6670000000000006 }, { index: 2, ratio: 1 }, { index: 3, ratio: 1 }, { index: 1, ratio: 2.409638554216892 }];
console.log(JSON.parse(JSON.stringify(array1)), JSON.parse(JSON.stringify(array2)));
var bestIndexArray = [];
while(array1.length) {
  var closest = findNearestRatio(array1[0], array2);
  closest.org = array1[0];
  for (var j = 1; j < array1.length; j++) {
    var closest2 = findNearestRatio(array1[j], array2);
    if(closest2.item.index === closest.item.index && closest.diff > closest2.diff) {
      closest2.org = array1[j];
      closest = closest2;
    }
  }                  
  bestIndexArray.push({array1: closest.org.index, array2:closest.item.index});
  array1.splice(array1.indexOf(closest.org), 1);
  array2.splice(array2.indexOf(closest.item), 1);
}
console.log(bestIndexArray);

OUTPUT OUTPUT

Upvotes: 0

Related Questions