Home > OS >  Find the index of closest number in array of objects in Javascript
Find the index of closest number in array of objects in Javascript

Time:02-16

Im using javascript for this. I have an dataset as followings:

var filteredValues = [{
                        type1 : [ ],
                        type2 : [{w:86,h:108,l:66}, {w:86,h:109,l:66}],
                        type3 : [{w:82,h:110,l:73}]
                     }]

I want to be able to filter this dataset to the nearest item based on the values of h provided by the user. Example: if the user provides 105 as h, the below would happen

  • type1 will be discarded as nothing is selected there at the moment.
  • 105 would match against h value of type2 and type3 and whichever is closest, would be selected. In this case, {w:86,h:108,l:66} from type2 as 105 is closest or equal to 109 or 110 (from type3) .
  • the result of the output would be the type name, in this case type2

Please feel free to correct the question if you see any mistakes. Also if you think changing dataset can make it easier, let me know.

Below are few interesting thread that may be helpful

How to find nearest element in nested array javascript?

Find object in array with closest value

Update:

I tried the following

function getResult(filteredValues, 105){
      filteredValues.reduce((acc, obj) =>
         Math.abs(y - obj.s) < Math.abs(y - acc.s) ? obj : acc
      );
}

Thank you very much in advance.

CodePudding user response:

I've just written this code and it seems to work, but it would need to be tested more (it's bigger but maybe more understandable):

const filteredValues = [
  {
    type1: [],
    type2: [
      { w: 86, h: 108, l: 66 },
      { w: 86, h: 109, l: 66 },
    ],
    type3: [{ w: 82, h: 106, l: 73 }],
  },
];

function filter(h) {
  const keys = Object.keys(filteredValues[0]);
  const values = Object.values(filteredValues[0]);
  const length = keys.length;
  let tempType = keys[0];
  let tempClosestHValue = values[0][0]?.h ?? Infinity;
  for (let i = 0; i < length; i  ) {
    const type = values[i];
    const key = keys[i];
    if (type.length > 0) {
      let closestHValue = Math.abs(type[0].h - h);
      for (let y = 0; y < values[i].length; y  ) {
        let data = values[i][y];
        if (Math.abs(data.h - h) < closestHValue) {
          closestHValue = data.h;
        }
      }
      if (closestHValue < tempClosestHValue) {
        tempClosestHValue = closestHValue;
        tempType = key;
      }
    }
  }
  return tempType;
}

console.log(filter(105));

which returns "type3", but if you modify the h property of the third type to 110, you get "type2" as the output.

CodePudding user response:

This solution takes only the object of the given data.

With the entries,

  • filter empty arrays
  • map the result of reducing the array by taking the absolute delta to get the smallest possible value to the target value.

At the end create a new object from entries.

const
    data = { type1: [], type2: [{ w: 86, h: 108, l: 66 }, { w: 86, h: 109, l: 66 }], type3: [{ w: 82, h: 110, l: 73 }] },
    height = 105,
    result = Object.fromEntries(Object
        .entries(data)
        .filter(([_, { length }]) => length)
        .map(([k, v]) => [k, v.reduce((a, b) => Math.abs(a.h - height) <= Math.abs(b.h - height)
            ? a
            : b
        )])
    );

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

  • Related