배열에서 가장 가까운 숫자를 얻습니다


163

마이너스 1000에서 플러스 1000까지의 숫자가 있고 숫자가있는 배열이 있습니다. 이처럼 :

[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]

내가 가진 숫자가 가장 가까운 배열 수로 변경되기를 원합니다.

예를 들어 나는 80숫자로 얻고 싶습니다 82.


2
불가능할 정도로 간단합니다 : 변수를 따로 설정하고 x배열을 하나씩 살펴보고 배열 i의 현재 숫자와 비교 하십시오. 그 차이 i가의 현재 값보다 작은 경우 현재 배열 번호로 x설정 x하십시오. 완료되면 배열에서 x가장 가까운 번호를 갖 습니다 i.
deceze

답변:


208

ES5 버전 :

var counts = [4, 9, 15, 6, 2],
  goal = 5;

var closest = counts.reduce(function(prev, curr) {
  return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});

console.log(closest);


1
단점은 reduce의 콜백이 선언 된 vars와 동일한 범위에서 호출 된 경우에만 작동한다는 것입니다. goal축소를 통과 할 수 없으므로 전역 범위에서이를 참조해야합니다.
7yl4r

5
고차 함수를 사용하여 그렇게 할 수도 있습니다.
dmp

3
@ 7yl4r 또는 함수로 감싸십니까? ;)
Dominic

1
@ 7yl4r은 실제로는 아닙니다 ... bind를 사용하여 이것을 달성 할 수 있습니다 ... ---------- // reducer.js function reducer (goal, prev, curr) {return (Math.abs (curr- goal) <Math.abs (prev-goal)? curr : prev); } // main.js var counts = [4, 9, 15, 6, 2], 목표 = 5; counts.reduce (reducer.bind (null, goal)); ---------- 주석에 코드를 넣는 방법을 모르겠습니다.
Mauricio Soares

이것은 목록이 주문 된 경우에 최적이 아닌 작은 항목에 대해서는 모든 항목을 반복합니다. 이진 검색이 없어도 다음 번호가 더 길면 루프가 종료 될 수 있습니다.
Dominic

144

다음은 모든 절차 언어로 변환 할 수있는 의사 코드입니다.

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

def closest (num, arr):
    curr = arr[0]
    foreach val in arr:
        if abs (num - val) < abs (num - curr):
            curr = val
    return curr

그것은 주어진 숫자와 각 배열 요소 사이의 절대적인 차이를 해결하고 최소한의 차이로 그중 하나를 돌려줍니다.

예제 값의 경우 :

number = 112  112  112  112  112  112  112  112  112  112
array  =   2   42   82  122  162  202  242  282  322  362
diff   = 110   70   30   10   50   90  130  170  210  250
                         |
                         +-- one with minimal absolute difference.

개념 증명으로, 이것을 실제로 사용하는 데 사용한 Python 코드는 다음과 같습니다.

def closest (num, arr):
    curr = arr[0]
    for index in range (len (arr)):
        if abs (num - arr[index]) < abs (num - curr):
            curr = arr[index]
    return curr

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

Javascript로 실제로 필요한 경우 작동하는 함수를 보여주는 완전한 HTML 파일은 아래를 참조하십시오.

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var curr = arr[0];
                var diff = Math.abs (num - curr);
                for (var val = 0; val < arr.length; val++) {
                    var newdiff = Math.abs (num - arr[val]);
                    if (newdiff < diff) {
                        diff = newdiff;
                        curr = arr[val];
                    }
                }
                return curr;
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

예를 들어 데이터 항목이 정렬 된 경우 (샘플 데이터에서 유추 할 수 있지만 명시 적으로 명시하지 않은 경우) 효율성이 향상 될 수 있습니다. 예를 들어 이진 검색을 사용하여 가장 가까운 항목을 찾을 수 있습니다.

또한 초당 여러 번 수행 해야하는 경우가 아니라면 데이터 세트가 훨씬 커지지 않는 한 효율성 향상은 거의 눈에 띄지 않습니다 .

당신이 경우 않는 그런 식으로 시도하는 (그리고 배열이 오름차순으로 정렬됩니다 보장 할 수 있습니다) 원하는, 이것은 좋은 출발점입니다 :

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var mid;
                var lo = 0;
                var hi = arr.length - 1;
                while (hi - lo > 1) {
                    mid = Math.floor ((lo + hi) / 2);
                    if (arr[mid] < num) {
                        lo = mid;
                    } else {
                        hi = mid;
                    }
                }
                if (num - arr[lo] <= arr[hi] - num) {
                    return arr[lo];
                }
                return arr[hi];
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

기본적으로 중간 값의 브라케팅 및 검사를 사용하여 각 반복에 대한 솔루션 공간을 절반으로 줄입니다. O(log N)위의 순차적 검색은 O(N)다음과 같습니다.

0  1  2   3   4   5   6   7   8   9  <- indexes
2 42 82 122 162 202 242 282 322 362  <- values
L             M                   H  L=0, H=9, M=4, 162 higher, H<-M
L     M       H                      L=0, H=4, M=2, 82 lower/equal, L<-M
      L   M   H                      L=2, H=4, M=3, 122 higher, H<-M
      L   H                          L=2, H=3, difference of 1 so exit
          ^
          |
          H (122-112=10) is closer than L (112-82=30) so choose H

언급했듯이 작은 데이터 집합이나 맹목적으로 빠를 필요 가없는 것들에는 큰 차이가 없어야 하지만 고려할 수있는 옵션입니다.


2
@micha, 답변에 eqivalent JS 코드를 추가했습니다. 언어에 익숙한 언어를 변경하는 데 시간이 걸렸습니다. :-)
paxdiablo

2
큰 데이터 세트가있는 경우이 알고리즘의 런타임이 좋지 않습니다.
ylun.ca

4
@ ylun.ca, 질문에 데이터가 정렬되어 있음 (예제가 정렬되었지만 일치 할 수 있음)이라는 명시 적 진술 이 없으므로 O (n)보다 더 나은 효율성을 얻을 수 없습니다. 어쨌든, 크기가 큰 데이터 세트의 경우 효율성은 대부분 관련이 없습니다. 그러나 귀하의 요점은 유효한 것이므로 그 대답에 메모를 추가하여 희망적으로 답변을보다 완전하게 만들 것입니다.
paxdiablo

1
한 번 이상 공표 할 수 있기를 바랍니다. 스택 오버플로에 대한 더 많은 답변은 이러한 노력을 기울여야합니다.
Richard Vanbergen

48

ES6 (2015) 버전 :

const counts = [4, 9, 15, 6, 2];
const goal = 5;

const output = counts.reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);

console.log(output);

재사용 성을 위해 자리 표시자를 지원하는 카레 함수 ( http://ramdajs.com/0.19.1/docs/#curry 또는 https://lodash.com/docs#curry )로 래핑 할 수 있습니다 . 이것은 필요한 것에 따라 많은 유연성을 제공합니다.

const getClosest = curry((counts, goal) => {
  return counts
    .reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});

const closestTo5 = getClosest(_, 5);
const closestTo = getClosest([4, 9, 15, 6, 2]);

24

아래와 같은 작업 코드 :

var array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

function closest(array, num) {
  var i = 0;
  var minDiff = 1000;
  var ans;
  for (i in array) {
    var m = Math.abs(num - array[i]);
    if (m < minDiff) {
      minDiff = m;
      ans = array[i];
    }
  }
  return ans;
}
console.log(closest(array, 88));


8
메리 어가 많을수록.
핫 릭

6
JavaScript 만 사용하기 때문에 이것이 더 나은 해결책이라고 주장합니다. 허용되는 답변은 원래 질문에서 언급되지 않았 으며이 질문을보고있는 다른 사람들이 사용하지 않을 수도있는 jQuery를 사용합니다.
Sean the Bean

17

정렬되지 않은 배열에서 작동

여기에 좋은 솔루션이 게시되어 있지만 JavaScript는 여러 가지 방법으로 문제를 해결할 수있는 도구를 제공하는 유연한 언어입니다. 물론 그것은 모두 당신의 스타일에 달려 있습니다. 코드가 더 기능적이라면 축소 변형이 적합하다는 것을 알게 될 것입니다 .

  arr.reduce(function (prev, curr) {
    return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
  });

그러나 일부는 코딩 스타일에 따라 읽기가 어려울 수 있습니다. 따라서 나는 문제를 해결하는 새로운 방법을 제안한다.

  var findClosest = function (x, arr) {
    var indexArr = arr.map(function(k) { return Math.abs(k - x) })
    var min = Math.min.apply(Math, indexArr)
    return arr[indexArr.indexOf(min)]
  }

  findClosest(80, [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]) // Outputs 82

반대로 다른 접근 하여 최소 값을 찾는는 Math.min.apply, 입력 배열을 필요로하지 않습니다이 하나 arr소트 . 인덱스를 신경 쓰거나 미리 정렬 할 필요는 없습니다.

명확성을 위해 코드를 한 줄씩 설명하겠습니다.

  1. arr.map(function(k) { return Math.abs(k - x) })주어진 숫자의 절대 값 ( arr)에서 입력 숫자를 뺀 값을 저장하는 새로운 배열을 만듭니다.x ) )를 . 다음으로 가장 작은 숫자를 찾습니다 (입력 숫자에 가장 가까운 숫자).
  2. Math.min.apply(Math, indexArr) 이것은 방금 전에 만든 배열에서 가장 작은 숫자를 찾는 합법적 인 방법입니다.
  3. arr[indexArr.indexOf(min)]아마도 가장 흥미로운 부분 일 것입니다. 가장 작은 숫자를 찾았지만 초기 숫자 ( x)를 더하거나 빼야할지 확실하지 않습니다 . 우리 Math.abs()가 차이점을 찾는 데 사용 되었기 때문 입니다. 그러나 array.map인덱스를 동일한 위치에 유지하면서 입력 배열의 맵을 (논리적으로) 만듭니다. 따라서 가장 가까운 숫자를 찾으려면 주어진 배열에서 찾은 최소값의 인덱스를 반환합니다 indexArr.indexOf(min).

그것을 보여주는 쓰레기통을 만들었 습니다.


1
잘 모르겠지만 3n2016 년에 실제로 답변하고 ES5 이므로 성능에 의심이있을 수 있습니다. 이 질문을 분명히 한이 멍청한 놈은 당시 프로그래머가 아니었지만 다른 솔루션은 괜찮습니다.
noob

1
그래, 당신이 배우는 것을 보는 것이 좋습니다! 그건 그렇고 실제로 성능이 나 빠졌다고 주장하지는 않지만 성능 문제에 대해서만 이야기했지만 숫자를 실행했으며 O(n)솔루션은 O(log n)임의의 숫자에서 @paxdiablo보다 약 100k ops / sec 적은 성능을 발휘 합니다. 알고리즘을 설계 할 때 항상 먼저 정렬합니다. (내가하는 일을 알고 백업 할 벤치 마크가있는 경우를 제외하고)
noob

1
간단한 해결책을 제시합니다. (내가 멍청한 놈이하는 것처럼 미리 정렬 된 배열을 갖는 사치가 필요하지 않습니다.) 내 사용 사례에 대한 좋은 작품
jaggedsoft

2
findClosest가 콜백 감소 함수를 반환하여 모든 배열에서 재사용 할 수 있도록 할 수 있습니다. const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
Jakob E

1
예 : [2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
Jakob E

11

정렬 된 배열 (선형 검색)

지금까지 모든 답변은 전체 배열을 검색하는 데 집중했습니다. 배열이 이미 정렬되어 있고 가장 가까운 숫자 만 원한다는 것을 고려할 때 아마도 가장 빠른 해결책 일 것입니다.

var a = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
var target = 90000;

/**
 * Returns the closest number from a sorted array.
 **/
function closest(arr, target) {
  if (!(arr) || arr.length == 0)
    return null;
  if (arr.length == 1)
    return arr[0];

  for (var i = 1; i < arr.length; i++) {
    // As soon as a number bigger than target is found, return the previous or current
    // number depending on which has smaller difference to the target.
    if (arr[i] > target) {
      var p = arr[i - 1];
      var c = arr[i]
      return Math.abs(p - target) < Math.abs(c - target) ? p : c;
    }
  }
  // No number in array is bigger so return the last.
  return arr[arr.length - 1];
}

// Trying it out
console.log(closest(a, target));

이진 트리를 사용하여 알고리즘을 크게 개선 할 수 있습니다.


이 전략은 훌륭하지만 몇 가지 오타가 있습니다. 예, a[i]또는 i[0].
웨슬리 노동자

1
감사합니다, @WesleyWorkman. 그냥 고 쳤어요 나는 모든 것을 얻었기를 바랍니다. 그런데 다른 사람의 답변을 편집 할 수도 있습니다.
허버트 Grzeskowiak

가장 가까운 값을 얻으려면 위의 응답 코드에서 수정 해야하는 곳은 어디입니까? 예 : [110, 111, 120, 140, 148, 149, 155, 177, 188, 190] 150을 검색하면 149가 아니라 155가되어야합니다. 시도했지만 문제를 해결하는 데 어려움이있었습니다. 도와주세요. 감사합니다
user1199842

9

모든 솔루션이 과도하게 설계되었습니다.

다음과 같이 간단합니다.

const needle = 5;
const haystack = [1, 2, 3, 4, 5, 6, 7, 8, 9];

haystack.sort((a, b) => {
  return Math.abs(a - needle) - Math.abs(b - needle);
});

// 5

1
실제로, 훨씬 더 많은 점. "배열에서 가장 가까운 숫자를 얻으려면"정렬 된 배열에서 첫 번째 요소를 선택해야합니다.
Shaya Ulman

6

이 솔루션은 조건이 충족되는 경우 반복을 중지 할 수있는 ES5 존재 수량 Array#some 자를 사용합니다.

와 반대로 Array#reduce, 하나의 결과에 대해 모든 요소를 ​​반복 할 필요는 없습니다.

콜백 내에서 delta검색된 값과 실제 값 사이의 절대 값item 이 취해져 마지막 델타와 비교됩니다. 델타가있는 다른 모든 값이 실제 값보다 크기 때문에 크거나 같으면 반복이 중지됩니다.

경우 delta콜백에서이 작은 다음, 실제 항목이 결과에 할당하고이 delta에 저장됩니다 lastDelta.

마지막으로 아래의 예와 같이 델타가 같은 값이 작을수록 22결과 는 다음과 같습니다 2.

더 큰 값의 우선 순위가있는 경우 델타 점검은 다음에서 변경되어야합니다.

if (delta >= lastDelta) {

에:

if (delta > lastDelta) {
//       ^^^ without equal sign

이것은으로 얻을 것 22, 결과42 (더 큰 값의 우선 순위).

이 함수는 배열에서 정렬 된 값이 필요합니다.


우선 순위가 작은 코드 :

function closestValue(array, value) {
    var result,
        lastDelta;

    array.some(function (item) {
        var delta = Math.abs(value - item);
        if (delta >= lastDelta) {
            return true;
        }
        result = item;
        lastDelta = delta;
    });
    return result;
}

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log(21, closestValue(data, 21)); // 2
console.log(22, closestValue(data, 22)); // 2  smaller value
console.log(23, closestValue(data, 23)); // 42
console.log(80, closestValue(data, 80)); // 82

우선 순위가 더 큰 코드 :

function closestValue(array, value) {
    var result,
        lastDelta;

    array.some(function (item) {
        var delta = Math.abs(value - item);
        if (delta > lastDelta) {
            return true;
        }
        result = item;
        lastDelta = delta;
    });
    return result;
}

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log(21, closestValue(data, 21)); //  2
console.log(22, closestValue(data, 22)); // 42 greater value
console.log(23, closestValue(data, 23)); // 42
console.log(80, closestValue(data, 80)); // 82


그래서 당신은 주어진 배열이 정렬되어 있다고 가정합니다 ... 그것은 지옥에서 많은 시간을 절약합니다.
Redu

1
op의 배열은 정렬 된 것처럼 보입니다. 그래서 그렇습니다 :)
Nina Scholz

첫 번째 솔루션은 같은 숫자가 두 번 포함 된 입력에서 나옵니다. 예closestValue([ 2, 2, 42, 80 ], 50) === 2
Sébastien Vercammen

@ SébastienVercammen, op의 데이터는 독특하고 정렬되었습니다.
Nina Scholz

@NinaScholz OP는 "숫자가있는 배열이 있습니다""가장 가까운 배열의 숫자로 변경하려는 숫자" 만 확인 했습니다 . 예제 배열은 하나의 예일뿐입니다. 배열은 고유 한 항목을 보장하지 않습니다.
Sébastien Vercammen

4

ES6

정렬 및 정렬되지 않은 배열에서 작동

숫자 정수 및 부동 소수점, 문자열 환영

/**
 * Finds the nearest value in an array of numbers.
 * Example: nearestValue(array, 42)
 * 
 * @param {Array<number>} arr
 * @param {number} val the ideal value for which the nearest or equal should be found
 */
const nearestValue = (arr, val) => arr.reduce((p, n) => (Math.abs(p) > Math.abs(n - val) ? n - val : p), Infinity) + val

예 :

let values = [1,2,3,4,5]
console.log(nearestValue(values, 10)) // --> 5
console.log(nearestValue(values, 0)) // --> 1
console.log(nearestValue(values, 2.5)) // --> 2

values = [100,5,90,56]
console.log(nearestValue(values, 42)) // --> 56

values = ['100','5','90','56']
console.log(nearestValue(values, 42)) // --> 56

3

이전 질문에 대답해야할지 모르겠지만이 게시물이 Google 검색에 처음 표시되므로 내 솔루션 및 2c를 여기에 추가하는 것을 용서해 주셨으면합니다.

게으 르기 때문에이 질문에 대한 해결책이 LOOP 일 것이라고 믿을 수 없었으므로 조금 더 검색하고 필터 기능으로 돌아 왔습니다 .

var myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
var myValue = 80;

function BiggerThan(inArray) {
  return inArray > myValue;
}

var arrBiggerElements = myArray.filter(BiggerThan);
var nextElement = Math.min.apply(null, arrBiggerElements);
alert(nextElement);

그게 다야 !


1
하한은 어떻습니까? 항상 다음으로 높은 값을 사용하십시오. 그러나 귀하의 접근 방식은 goog.math.clamp배열을 사용하고 하한을 신경 쓰지 않고 (Google 폐쇄)를 상기시킵니다 .
noob

솔루션은 배열에서 다음으로 높은 숫자를 반환합니다. 가장 가까운 값이나 정확한 값을 찾을 수 없습니다.
허버트 그제 스코 위크

2

비슷한 질문에 대한 나의 대답도 관계를 설명하고 일반 자바 스크립트이지만 바이너리 검색을 사용하지 않으므로 O (N)이며 O (logN)이 아닙니다.

var searchArray= [0, 30, 60, 90];
var element= 33;

function findClosest(array,elem){
    var minDelta = null;
    var minIndex = null;
    for (var i = 0 ; i<array.length; i++){
        var delta = Math.abs(array[i]-elem);
        if (minDelta == null || delta < minDelta){
            minDelta = delta;
            minIndex = i;
        }
        //if it is a tie return an array of both values
        else if (delta == minDelta) {
            return [array[minIndex],array[i]];
        }//if it has already found the closest value
        else {
            return array[i-1];
        }

    }
    return array[minIndex];
}
var closest = findClosest(searchArray,element);

https://stackoverflow.com/a/26429528/986160


2

Fusion의 접근 방식이 마음에 들지만 약간의 오류가 있습니다. 그런 식으로 맞습니다 :

    function closest(array, number) {
        var num = 0;
        for (var i = array.length - 1; i >= 0; i--) {
            if(Math.abs(number - array[i]) < Math.abs(number - array[num])){
                num = i;
            }
        }
        return array[num];
    }

또한 향상된 for루프를 사용하기 때문에 조금 더 빠릅니다 .

결국 나는 다음과 같이 내 기능을 썼다.

    var getClosest = function(number, array) {
        var current = array[0];
        var difference = Math.abs(number - current);
        var index = array.length;
        while (index--) {
            var newDifference = Math.abs(number - array[index]);
            if (newDifference < difference) {
                difference = newDifference;
                current = array[index];
            }
        }
        return current;
    };

나는 그것을 테스트 console.time()했고 다른 기능보다 약간 빠르다.


이봐, 왜 그런지 설명 할 수 improved for loop있니? 역 루프가 항상 성능 향상은 아닙니다.
A1rPun

이 루프에 대해서는 .length선언 할 때 한 번만 평가 합니다 i. 하지만 var i = arr.length;while (i--) {}더 빠를 것 같아요
Jon

내 답변을 업데이트했습니다. 로 변경했습니다 while. 이제는 더 빠릅니다.
Jon

0

배열에서 약간 수정 된 이진 검색이 작동합니다.


3
이봐, 기이 한 일이다. 누군가 이진 검색을 좋아하지 않는 것 같다. (그것이 가장 일반적인 해결책이라고 생각했습니다.)
핫 릭

0

작은 범위의 경우 가장 간단한 방법은 맵 배열을 사용하는 것입니다. 예를 들어 80 번째 항목에 82 값이 있으면 예제를 사용할 수 있습니다. 훨씬 더 큰 희소 범위의 경우 아마도 이진 검색 일 것입니다.

쿼리 언어를 사용하면 입력 번호의 어느 정도 거리를두고 값을 쿼리 한 다음 축소 목록을 정렬 할 수 있습니다. 그러나 SQL에는 "다음"또는 "이전"개념이 없어 "깨끗한"솔루션을 제공 할 수 있습니다.


0

여기서 또 다른 변형은 머리와 발끝을 연결하는 원형 범위를 가지며 주어진 입력에 최소값 만 허용합니다. 이것은 암호화 알고리즘 중 하나에 대한 char 코드 값을 얻는 데 도움이되었습니다.

function closestNumberInCircularRange(codes, charCode) {
  return codes.reduce((p_code, c_code)=>{
    if(((Math.abs(p_code-charCode) > Math.abs(c_code-charCode)) || p_code > charCode) && c_code < charCode){
      return c_code;
    }else if(p_code < charCode){
      return p_code;
    }else if(p_code > charCode && c_code > charCode){
      return Math.max.apply(Math, [p_code, c_code]);
    }
    return p_code;
  });
}

0
#include <algorithm>
#include <iostream>
#include <cmath>

using namespace std;

class CompareFunctor
{

public:
    CompareFunctor(int n) { _n = n; }
    bool operator()(int & val1, int & val2)
    {
        int diff1 = abs(val1 - _n);
        int diff2 = abs(val2 - _n);
        return (diff1 < diff2);
    }

private:
    int _n;
};

int Find_Closest_Value(int nums[], int size, int n)
{
    CompareFunctor cf(n);
    int cn = *min_element(nums, nums + size, cf);
    return cn;
}

int main()
{
    int nums[] = { 2, 42, 82, 122, 162, 202, 242, 282, 322, 362 };
    int size = sizeof(nums) / sizeof(int);
    int n = 80;
    int cn = Find_Closest_Value(nums, size, n);
    cout << "\nClosest value = " << cn << endl;
    cin.get();
}

0

가장 효율적인 이진 검색입니다. 그러나 다음 번호가 현재 번호와 더 일치 하면 간단한 솔루션도 종료 될 수 있습니다 . 여기의 거의 모든 솔루션은 배열이 주문되고 전체를 통해 반복된다는 것을 고려하지 않았습니다.

const closest = (orderedArray, value, valueGetter = item => item) =>
  orderedArray.find((item, i) =>
    i === orderedArray.length - 1 ||
    Math.abs(value - valueGetter(item)) < Math.abs(value - valueGetter(orderedArray[i + 1])));

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log('21 -> 2', closest(data, 21) === 2);
console.log('22 -> 42', closest(data, 22) === 42); // equidistant between 2 and 42, select highest
console.log('23 -> 42', closest(data, 23) === 42);
console.log('80 -> 82', closest(data, 80) === 82);

이것은 기본이 아닌 것에서도 실행될 수 있습니다. closest(data, 21, item => item.age)

변경 find하는 findIndex배열의 인덱스를 반환합니다.


정렬되지 않은 배열은 어떻습니까?
EdG

정렬되지 않은 경우 종료되지 않는 솔루션 중 하나를 사용하십시오.하지만 여러 번 작업을 수행하는 경우 배열을 한 번 정렬하는 것이 가장 좋습니다. 언급했듯이 배열이 실제로 큰 경우 이진 검색은 선형 검색보다 효율적입니다.
도미닉

0

배열에서 가장 가까운 두 개의 숫자를 찾으려면

function findTwoClosest(givenList, goal) {
  var first;
  var second;
  var finalCollection = [givenList[0], givenList[1]];
  givenList.forEach((item, firtIndex) => {
    first = item;

    for (let i = firtIndex + 1; i < givenList.length; i++) {
      second = givenList[i];

      if (first + second < goal) {
        if (first + second > finalCollection[0] + finalCollection[1]) {
          finalCollection = [first, second];
        }
      }
    }
  });

  return finalCollection;
}

var counts = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
var goal = 80;
console.log(findTwoClosest(counts, goal));

-5

Complexity O (nlog (n))의 배열에서 숫자에 가장 가까운 요소를 찾는 코드 스 니펫은 다음과 같습니다.

입력 :-{1,60,0, -10,100,87,56} 요소 :-56 배열에서 가장 가까운 수 :-60

소스 코드 (자바) :

package com.algo.closestnumberinarray;
import java.util.TreeMap;


public class Find_Closest_Number_In_Array {

    public static void main(String arsg[]) {
        int array[] = { 1, 60, 0, -10, 100, 87, 69 };
        int number = 56;
        int num = getClosestNumber(array, number);
        System.out.println("Number is=" + num);
    }

    public static int getClosestNumber(int[] array, int number) {
        int diff[] = new int[array.length];

        TreeMap<Integer, Integer> keyVal = new TreeMap<Integer, Integer>();
        for (int i = 0; i < array.length; i++) {

            if (array[i] > number) {
                diff[i] = array[i] - number;
                keyVal.put(diff[i], array[i]);
            } else {
                diff[i] = number - array[i];
                keyVal.put(diff[i], array[i]);
            }

        }

        int closestKey = keyVal.firstKey();
        int closestVal = keyVal.get(closestKey);

        return closestVal;
    }
}

Post 태그에 자바 스크립트를 요청 함
Shannon Hochkins 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.