obtenir le nombre le plus proche du tableau

163

J'ai un nombre de moins 1000 à plus 1000 et j'ai un tableau avec des nombres. Comme ça:

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

Je veux que le nombre que j'ai change au nombre le plus proche du tableau.

Par exemple, j'obtiens 80le nombre que je veux 82.

Noob
la source
2
Incroyablement simple: mettez de côté une variable x, parcourez le tableau un par un, comparez-le iau nombre actuel du tableau, si la différence entre celui-ci et iest inférieure à la valeur actuelle dans x, définissez xle numéro du tableau actuel. Une fois terminé, xa le numéro le plus proche idu tableau.
deceze

Réponses:

208

Version 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);

Joe Grund
la source
1
l'inconvénient est que cela ne fonctionne que si le rappel de reduction est appelé depuis la même portée que les variables déclarées. Puisque vous ne pouvez pas passer goalpour réduire, vous devez le référencer à partir d'une portée globale.
7yl4r
5
pourrait utiliser une fonction d'ordre supérieur pour le faire aussi.
dmp
3
@ 7yl4r ou l'envelopper dans une fonction? ;)
Dominic
1
@ 7yl4r pas vraiment ... vous pouvez utiliser bind pour y parvenir ... ---------- // reducer.js function reducer (goal, prev, curr) {return (Math.abs (curr - objectif) <Math.abs (prev - but)? curr: prev); } // main.js var compte = [4, 9, 15, 6, 2], objectif = 5; count.reduce (reducer.bind (null, but)); ---------- Je ne sais pas comment mettre du code dans les commentaires hahaha.
Mauricio Soares
Cela itère sur chaque élément, ce qui n'est pas optimal si la liste est ordonnée mais ok pour les petites listes. Même sans recherche binaire, une boucle pourrait se terminer si le numéro suivant est plus loin.
Dominic
144

Voici le pseudo-code qui devrait être convertible dans n'importe quel langage procédural:

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

Il calcule simplement les différences absolues entre le nombre donné et chaque élément du tableau et vous rend l'un de ceux avec la différence minimale.

Pour les exemples de valeurs:

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.

En guise de preuve de concept, voici le code Python que j'ai utilisé pour montrer cela en action:

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)

Et, si vous en avez vraiment besoin en Javascript, voyez ci-dessous un fichier HTML complet qui montre la fonction en action:

<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>

Maintenant, gardez à l'esprit qu'il peut être possible d'améliorer l'efficacité si, par exemple, vos éléments de données sont triés (cela pourrait être déduit des exemples de données, mais vous ne l'indiquez pas explicitement). Vous pouvez, par exemple, utiliser une recherche binaire pour trouver l'élément le plus proche.

Vous devez également garder à l'esprit que, à moins que vous ne deviez le faire plusieurs fois par seconde, les améliorations d'efficacité seront pour la plupart imperceptibles à moins que vos ensembles de données ne deviennent beaucoup plus volumineux.

Si vous ne voulez essayer cette façon (et peut garantir le tableau est trié dans l' ordre croissant), c'est un bon point de départ:

<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>

Il utilise essentiellement le bracketing et la vérification de la valeur médiane pour réduire de moitié l'espace de solution pour chaque itération, un O(log N)algorithme classique alors que la recherche séquentielle ci-dessus était 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

Comme indiqué, cela ne devrait pas faire beaucoup de différence pour les petits ensembles de données ou pour les choses qui n'ont pas besoin d'être incroyablement rapides, mais c'est une option que vous voudrez peut-être envisager.

paxdiablo
la source
2
@micha, j'ai ajouté le code JS équivalent à la réponse, il a juste fallu un certain temps pour changer de langue d'une langue à laquelle j'étais plus habitué :-)
paxdiablo
2
Mauvaise exécution pour cet algorithme si vous avez de grands ensembles de données.
ylun.ca
4
@ ylun.ca, puisqu'il n'y a pas d' énoncé explicite dans la question que les données sont triées (l'exemple est trié mais cela peut être une coïncidence), vous ne pouvez pas obtenir une meilleure efficacité que O (n). Dans tous les cas, pour un ensemble de données de cette taille, l'efficacité n'a généralement pas d'importance. Mais votre argument est valable, je vais donc ajouter des notes à cet effet pour, espérons-le, rendre la réponse plus complète.
paxdiablo
1
Merci, j'aurais aimé pouvoir voter plus d'une fois! Plus de réponses sur le débordement de pile devraient avoir ce genre d'effort.
Richard Vanbergen
48

Version 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);

Pour la réutilisation, vous pouvez intégrer une fonction curry qui prend en charge les espaces réservés ( http://ramdajs.com/0.19.1/docs/#curry ou https://lodash.com/docs#curry ). Cela donne beaucoup de flexibilité en fonction de ce dont vous avez besoin:

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]);
Joe Grund
la source
24

Code de travail comme ci-dessous:

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));

Umesh Patil
la source
8
Plus on est de fous, plus on rit.
Hot Licks
6
Je dirais que c'est une meilleure solution car elle n'utilise que JavaScript. La réponse acceptée utilise jQuery, qui n'a pas été mentionné dans la question d'origine, et que d'autres personnes qui examinent cette question n'utilisent peut-être pas.
Sean the Bean
17

Fonctionne avec des tableaux non triés

Bien qu'il y ait eu quelques bonnes solutions publiées ici, JavaScript est un langage flexible qui nous donne des outils pour résoudre un problème de différentes manières. Tout dépend de votre style, bien sûr. Si votre code est plus fonctionnel, vous trouverez la variante de réduction appropriée, c'est-à-dire:

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

Cependant, certains peuvent trouver cela difficile à lire, en fonction de leur style de codage. C'est pourquoi je propose une nouvelle façon de résoudre le problème:

  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

Contrairement à d' autres approches pour trouver la valeur minimale à l'aide de Math.min.apply, celle-ci ne nécessite pas le arrtri du tableau d'entrée . Nous n'avons pas besoin de nous soucier des index ou de les trier au préalable.

Je vais vous expliquer le code ligne par ligne pour plus de clarté:

  1. arr.map(function(k) { return Math.abs(k - x) })Crée un nouveau tableau, stockant essentiellement les valeurs absolues des nombres donnés (nombre dans arr) moins le nombre d'entrée ( x). Nous chercherons ensuite le plus petit nombre (qui est également le plus proche du nombre d'entrée)
  2. Math.min.apply(Math, indexArr) C'est un moyen légitime de trouver le plus petit nombre dans le tableau que nous venons de créer auparavant (rien de plus)
  3. arr[indexArr.indexOf(min)]C'est peut-être la partie la plus intéressante. Nous avons trouvé notre plus petit nombre, mais nous ne savons pas si nous devons ajouter ou soustraire le nombre initial ( x). C'est parce que nous avions l'habitude Math.abs()de trouver la différence. Cependant, array.mapcrée (logiquement) une carte du tableau d'entrée, en gardant les index au même endroit. Par conséquent, pour trouver le nombre le plus proche, nous renvoyons simplement l'index du minimum trouvé dans le tableau donné indexArr.indexOf(min).

J'ai créé un bac pour le démontrer.

Dan Mindru
la source
1
Je ne sais pas mais je suppose que l'on pourrait avoir des doutes sur les performances car c'est pratiquement 3net c'est ES5 même si vous répondez en 2016 et que d'autres solutions sont très bien, même si ce noob qui a posé cette question n'était clairement pas un programmeur à l'époque.
noob
1
Ouais c'est super de te voir apprendre! En passant, je n'ai parlé que des doutes sur les performances, sans prétendre que les performances étaient moins bonnes, mais j'ai couru les chiffres pour vous et votre O(n)solution effectue environ 100000 opérations / s de moins que @paxdiablo O(log n)sur des nombres aléatoires. Lors de la conception d'un algorithme, trier toujours en premier, disent-ils. (Sauf si vous savez ce que vous faites et que vous avez des repères pour vous soutenir.)
noob
1
Accessoires pour la solution simple. Fonctionne très bien pour mon cas d'utilisation (je n'ai pas le luxe d'avoir un tableau pré-trié comme le fait noob.)
jaggedsoft
2
Vous pouvez faire en sorte que findClosest renvoie une fonction de rappel de réduction pour le rendre réutilisable sur tous les tableaux: const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
Jakob E
1
Exemple: [2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
Jakob E
11

Pour les tableaux triés (recherche linéaire)

Toutes les réponses jusqu'à présent se concentrent sur la recherche dans l'ensemble du tableau. Étant donné que votre tableau est déjà trié et que vous ne voulez vraiment que le nombre le plus proche, c'est probablement la solution la plus rapide:

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));

Notez que l'algorithme peut être considérablement amélioré, par exemple en utilisant un arbre binaire.

Hubert Grzeskowiak
la source
Bien que cette stratégie soit bonne ici, elle comporte plusieurs fautes de frappe. Exemple, a[i]ou i[0].
Wesley Workman
1
Merci, @WesleyWorkman. Je viens de les réparer. J'espère que j'ai tout. En passant, vous pouvez également modifier les réponses des autres.
Hubert Grzeskowiak
Où dois-je faire la correction dans le code de réponse ci-dessus pour obtenir la valeur la plus proche la plus élevée? Exemple: [110, 111, 120, 140, 148, 149, 155, 177, 188, 190] Si je recherche 150, je devrais obtenir 155 et non 149. J'ai essayé mais j'ai trouvé des difficultés à résoudre ce problème. S'il te plait peux-tu aider. Merci
user1199842
9

Toutes les solutions sont sur-conçues.

C'est aussi simple que:

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
Gajus
la source
1
En effet, beaucoup plus au point. mais pour "obtenir le nombre le plus proche du tableau", vous devez toujours sélectionner le premier élément du tableau trié.
Shaya Ulman
6

Cette solution utilise le quantificateur existentiel ES5 Array#some, qui permet d'arrêter l'itération, si une condition est remplie.

À l'opposé de Array#reduce, il n'est pas nécessaire d'itérer tous les éléments pour un résultat.

À l'intérieur du rappel, un absolu deltaentre la valeur recherchée et le réelitem est pris et comparé au dernier delta. Si elle est supérieure ou égale, l'itération s'arrête, car toutes les autres valeurs avec leurs deltas sont supérieures à la valeur réelle.

Si le deltadans le rappel est plus petit, alors l'élément réel est affecté au résultat et le deltaest enregistré dans lastDelta.

Enfin, des valeurs plus petites avec des deltas égaux sont prises, comme dans l'exemple ci-dessous de 22, qui aboutit à 2.

S'il existe une priorité de valeurs supérieures, le contrôle delta doit être modifié de:

if (delta >= lastDelta) {

à:

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

Ce serait avec 22, le résultat42 (priorité des valeurs supérieures).

Cette fonction nécessite des valeurs triées dans le tableau.


Code avec priorité de valeurs plus petites:

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

Code avec priorité de valeurs supérieures:

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

Nina Scholz
la source
Donc, vous supposez que le tableau donné est trié ... Cela vous fait gagner beaucoup de temps.
Réduit le
1
le tableau de l'op semble trié, donc oui :)
Nina Scholz
La première solution est interrompue sur les entrées contenant le même nombre deux fois. egclosestValue([ 2, 2, 42, 80 ], 50) === 2
Sébastien Vercammen le
@ SébastienVercammen, les données d'op sont uniques et triées.
Nina Scholz le
@NinaScholz OP a seulement déterminé "J'ai un tableau avec des nombres" et "Je veux que le numéro que j'ai change au nombre le plus proche du tableau" . L'exemple de tableau n'était qu'un exemple. Un tableau ne garantit pas des entrées uniques.
Sébastien Vercammen le
4

ES6

Fonctionne avec des tableaux triés et non triés

Nombres entiers et flottants, chaînes bienvenues

/**
 * 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

Exemples:

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
Sébastien
la source
3

Je ne sais pas si je suis censé répondre à une vieille question, mais comme ce message apparaît en premier sur les recherches Google, j'espérais que vous me pardonneriez d'ajouter ma solution et mon 2c ici.

Étant paresseux, je ne pouvais pas croire que la solution à cette question serait une BOUCLE, alors j'ai cherché un peu plus et suis revenu avec la fonction de filtre :

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);

C'est tout !

FrenchieFred
la source
1
Alors, qu'en est-il de la limite inférieure? Vous utilisez toujours la valeur immédiatement supérieure. Mais votre approche me rappelle goog.math.clamp(fermeture de google) uniquement avec des tableaux et sans prendre en compte la limite inférieure.
noob
Votre solution renvoie le nombre supérieur suivant du tableau. Ni la valeur la plus proche ni la valeur exacte ne sont trouvées.
Hubert Grzeskowiak
2

Ma réponse à une question similaire tient également compte des liens et elle est en Javascript simple, bien qu'elle n'utilise pas la recherche binaire, donc c'est O (N) et non 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

Michail Michailidis
la source
2

J'aime l'approche de Fusion, mais il y a une petite erreur. Comme ça c'est correct:

    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];
    }

C'est aussi un peu plus rapide car il utilise la forboucle améliorée .

À la fin, j'ai écrit ma fonction comme ceci:

    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;
    };

Je l'ai testé avec console.time()et il est légèrement plus rapide que l'autre fonction.

Jon
la source
Hé, peux-tu expliquer pourquoi c'est un improved for loop? Les boucles inversées ne sont pas toujours une amélioration des performances.
A1rPun
Vous n'évaluez .lengthqu'une fois, lorsque vous déclarez i, alors que pour cette boucle. Mais je pense que ce var i = arr.length;while (i--) {}serait encore plus rapide
Jon
J'ai mis à jour ma réponse. Je l'ai changé en while. Maintenant c'est encore plus rapide.
Jon
0

Une recherche binaire légèrement modifiée sur le tableau fonctionnerait.

Holygeek
la source
3
Gee, c'est bizarre - apparemment, quelqu'un n'aime pas les recherches binaires. (Même pensé que c'est la meilleure solution générale.)
Hot Licks
0

Pour une petite plage, le plus simple est d'avoir un tableau de cartes, où, par exemple, la 80e entrée aurait la valeur 82, pour utiliser votre exemple. Pour une plage beaucoup plus large et clairsemée, la recherche binaire est probablement la solution.

Avec un langage de requête, vous pouvez rechercher des valeurs à une certaine distance de chaque côté de votre numéro d'entrée, puis trier la liste réduite résultante. Mais SQL n'a pas un bon concept de "suivant" ou "précédent", pour vous donner une solution "propre".

Hot Licks
la source
0

Une autre variante ici, nous avons une plage circulaire reliant la tête aux pieds et n'accepte que la valeur minimale pour une entrée donnée. Cela m'avait aidé à obtenir des valeurs de code char pour l'un des algorithmes de cryptage.

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;
  });
}
Vikas
la source
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();
}
Rushikesh
la source
0

Le plus efficace serait une recherche binaire. Cependant, même des solutions simples peuvent sortir lorsque le numéro suivant est une autre correspondance par rapport au courant . Presque toutes les solutions ici ne prennent pas en compte le fait que le tableau est ordonné et itéré à travers le tout: /

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);

Cela peut également être exécuté sur des non-primitives, par exemple closest(data, 21, item => item.age)

Remplacez findpar findIndexpour renvoyer l'index dans le tableau.

Dominique
la source
Qu'en est-il du tableau non ordonné?
EdG
Pour les non-ordonnés, prenez l'une des solutions qui ne se termine pas, mais si vous effectuez le travail plusieurs fois, il peut être plus optimal de trier le tableau une fois. Comme mentionné, si le tableau est vraiment grand, une recherche binaire sera plus efficace qu'une recherche linéaire.
Dominic
0

Pour rechercher deux nombres les plus proches dans le tableau

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));
M Abdullah
la source
-5

Voici l'extrait de code pour trouver l'élément le plus proche d'un nombre à partir d'un tableau dans Complexity O (nlog (n)): -

Entrée: - {1,60,0, -10,100,87,56} Élément: - 56 Nombre le plus proche du tableau: - 60

Code source (Java):

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;
    }
}
Dead Pool
la source
Message demandé du javascript dans les tags
Shannon Hochkins