마이너스 1000에서 플러스 1000까지의 숫자가 있고 숫자가있는 배열이 있습니다. 이처럼 :
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
내가 가진 숫자가 가장 가까운 배열 수로 변경되기를 원합니다.
예를 들어 나는 80
숫자로 얻고 싶습니다 82
.
답변
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);
답변
다음은 모든 절차 언어로 변환 할 수있는 의사 코드입니다.
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
언급했듯이 작은 데이터 집합이나 맹목적으로 빠를 필요 가없는 것들에는 큰 차이가 없어야 하지만 고려할 수있는 옵션입니다.
답변
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]);
답변
아래와 같은 작업 코드 :
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));
답변
정렬되지 않은 배열에서 작동
여기에 좋은 솔루션이 게시되어 있지만 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
소트 . 인덱스를 신경 쓰거나 미리 정렬 할 필요는 없습니다.
명확성을 위해 코드를 한 줄씩 설명하겠습니다.
arr.map(function(k) { return Math.abs(k - x) })
주어진 숫자의 절대 값 (arr
)에서 입력 숫자를 뺀 값을 저장하는 새로운 배열을 만듭니다.x
) )를 . 다음으로 가장 작은 숫자를 찾습니다 (입력 숫자에 가장 가까운 숫자).Math.min.apply(Math, indexArr)
이것은 방금 전에 만든 배열에서 가장 작은 숫자를 찾는 합법적 인 방법입니다.arr[indexArr.indexOf(min)]
아마도 가장 흥미로운 부분 일 것입니다. 가장 작은 숫자를 찾았지만 초기 숫자 (x
)를 더하거나 빼야할지 확실하지 않습니다 . 우리Math.abs()
가 차이점을 찾는 데 사용 되었기 때문 입니다. 그러나array.map
인덱스를 동일한 위치에 유지하면서 입력 배열의 맵을 (논리적으로) 만듭니다. 따라서 가장 가까운 숫자를 찾으려면 주어진 배열에서 찾은 최소값의 인덱스를 반환합니다indexArr.indexOf(min)
.
그것을 보여주는 쓰레기통을 만들었 습니다.
답변
정렬 된 배열 (선형 검색)
지금까지 모든 답변은 전체 배열을 검색하는 데 집중했습니다. 배열이 이미 정렬되어 있고 가장 가까운 숫자 만 원한다는 것을 고려할 때 아마도 가장 빠른 해결책 일 것입니다.
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));
이진 트리를 사용하여 알고리즘을 크게 개선 할 수 있습니다.
답변
모든 솔루션이 과도하게 설계되었습니다.
다음과 같이 간단합니다.
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