[SOLVED] Get 5 closest elements to an element in array including that element

Issue

This Content is from Stack Overflow. Question asked by jorganinho

I am trying to get 5 closest elements to given element, including that element, in array. For example, if we have:

const arr = [1, 2, 3, 4, 7, 11, 12, 13, 15, 17]

and I want to get 5 closest elements to 11, it should return [4, 7, 11, 12, 13]. If i pass 1 it should return [1, 2, 3, 4, 7]. If I pass 15 it should return [11, 12, 13, 15, 17].



Solution

I’m not sure what you meant;

You might’ve meant a code to find the element and return the five nearest elements to it by place in the array;

Or you might’ve meant a code to find the 5 numbers closest to a number you say.

IF you meant the first case

There are two ways to do so,

A value as a parameter

Use this code:

function closestNByValue(arr, value, n) {
    let ind = arr.indexOf(value);
    let finalArr = [];
    if (n > arr.length) {
        finalArr = Array.from(arr);
    } else if (ind == -1) {
        finalArr = [];
    } else if (ind <= n/2 - 0.5) {
        finalArr = arr.slice(0, n);
    } else if (ind >= (arr.length - n/2) - 0.5) {
        finalArr = arr.slice(-n);
    } else if (n%2 == 0) {
        finalArr = arr.slice(ind-(n/2), ind+(n/2));
    } else {
        finalArr = arr.slice(ind-(n/2 - 0.5), ind+(n/2 + 0.5));
    }
    return finalArr;
}

console.log(closestNByValue([1, 2, 3, 4, 7, 11, 12, 13, 15, 17], 11, 5))

How does it do the job?

Okay first we need to find the index of the value and save it in ind (short form of ‘index’) and we check multiple different situations for what the ind is so we’d be able to output the best answer as finalArr.

There are two exceptions; what if there was no such value in our array? then ind = -1 and we’d return an empty array; or what if the number of elements nearby that we seek is larger than or equal to the arr.length? then we’d return all of the arr.

But if there were no exceptions, there are three different situations for the ind; first, ind is a number that makes us have all of the finalArr values from the first of arr, second, ind be a number that makes us have all of the finalArr values from the last of arr, and third, ind being a number that we have to select half from the indexes smaller than ind and half, larger.

If it is the third way, the way we select we’d be different depending on the oddity of the numbers we want to select.

And we’ll have a conditional statement for each situation and return the finalArr.

An index as a parameter

function closestNByIndex(arr, ind, n) {
    let finalArr = [];
    if (n > arr.length) {
        finalArr = Array.from(arr);
    } else if (ind == -1) {
        finalArr = [];
    } else if (ind <= n/2 - 0.5) {
        finalArr = arr.slice(0, n);
    } else if (ind >= (arr.length - n/2) - 0.5) {
        finalArr = arr.slice(-n);
    } else if (n%2 == 0) {
        finalArr = arr.slice(ind-(n/2), ind+(n/2));
    } else {
        finalArr = arr.slice(ind-(n/2 - 0.5), ind+(n/2 + 0.5));
    }
    return finalArr;
}
console.log(closestNByIndex([1, 2, 3, 4, 7, 11, 12, 13, 15, 17], 5, 5))

Similar to the first code it works, though we have the index and we don’t search for it.

The point is, if you use the function with value, it’d do the nearest 5 elements of the first value that equals the entry but such confusion is not being tolerated in the second code.

IF you meant the second case

This is a code I coded:

const arr = [1, 2, 3, 4, 7, 11, 12, 13, 15, 17];

function allDiff(arr, num1, num2) {
  const finalArr = [];
  const x = Math.abs(num2 - num1);
  for (let y = 0; y < arr.length; y++) {
    if (Math.abs(arr[y] - num1) == x) {
      finalArr.push(arr[y]);
    }
  }
  return finalArr;
}

function deleteArr(arr, delet) {
  for (let x = 0; x < arr.length; x++) {
    if (delet.includes(arr[x])) {
      delete arr[x];
    }
  }
  return arr;
}

function closest(arr, num) {
  const map = new Map()
  arr2 = Array.from(arr);
  let key, value;
  for (let x = 0; x < arr2.length; x++) {
    key = Math.abs(arr2[x] - num);
    value = allDiff(arr2, num, arr2[x]);
    arr2 = deleteArr(arr2, value);
    map.set(key, value);
  }
  return map;
}

function closestN(arr, num, n) {
  const map = closest(arr, num);
  const mapKeys = Array.from(map.keys());
  const mapKeysSorted = mapKeys.sort(function(a, b) {
    return a - b
  });
  let finalArr = [];
  let y;
  for (let i = 0; i < mapKeysSorted.length; i++) {
    if (n <= 0) {
      break;
    }
    y = map.get(mapKeysSorted[i]);
    if (n < y.length) {
      finalArr = finalArr.concat(y.slice(0, n + 1));
      break;
    }
    finalArr = finalArr.concat(y);
    n -= y.length;
  }
  return finalArr;
}
console.log(closestN(arr, 11, 5));

It might be a little too long, but I have programmed it as you can give it any array (arr) with integer values, an integer (num) that you’d like it to be the base and another integer (n) for the number of the size of the output array, 5 in this case.

Explaining the code

The function closest would return a map of (the difference between the numbers, a list of the numbers in the arr that differs the number equal to their key).

The main function, closestN, calls the closest function and saves the map in the map variable.

Then it sorts the keys of the map in mapKeysSorted.

Now, a for loop loops through the mapKeySorted array and pushes new elements to the finalArr until the size of the finalArr reaches the number of elements we seek.

The main function is the closestN.


This Question was asked in StackOverflow by jorganinho and Answered by Merlin the Immortal It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?