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 80
le nombre que je veux 82
.
javascript
arrays
Noob
la source
la source
x
, parcourez le tableau un par un, comparez-lei
au nombre actuel du tableau, si la différence entre celui-ci eti
est inférieure à la valeur actuelle dansx
, définissezx
le numéro du tableau actuel. Une fois terminé,x
a le numéro le plus prochei
du tableau.Réponses:
Version ES5:
la source
goal
pour réduire, vous devez le référencer à partir d'une portée globale.Voici le pseudo-code qui devrait être convertible dans n'importe quel langage procédural:
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:
En guise de preuve de concept, voici le code Python que j'ai utilisé pour montrer cela en action:
Et, si vous en avez vraiment besoin en Javascript, voyez ci-dessous un fichier HTML complet qui montre la fonction en action:
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:
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 étaitO(N)
: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.
la source
Version ES6 (2015):
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:
la source
Code de travail comme ci-dessous:
la source
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:
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:
Contrairement à d' autres approches pour trouver la valeur minimale à l'aide de
Math.min.apply
, celle-ci ne nécessite pas learr
tri 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é:
arr.map(function(k) { return Math.abs(k - x) })
Crée un nouveau tableau, stockant essentiellement les valeurs absolues des nombres donnés (nombre dansarr
) 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)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)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'habitudeMath.abs()
de trouver la différence. Cependant,array.map
cré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.
la source
3n
et 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.O(n)
solution effectue environ 100000 opérations / s de moins que @paxdiabloO(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.)const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
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:
Notez que l'algorithme peut être considérablement amélioré, par exemple en utilisant un arbre binaire.
la source
a[i]
oui[0]
.Toutes les solutions sont sur-conçues.
C'est aussi simple que:
la source
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
delta
entre 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
delta
dans le rappel est plus petit, alors l'élément réel est affecté au résultat et ledelta
est enregistré danslastDelta
.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:
à:
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:
Code avec priorité de valeurs supérieures:
la source
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Fonctionne avec des tableaux triés et non triés
Nombres entiers et flottants, chaînes bienvenues
Exemples:
la source
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 :
C'est tout !
la source
goog.math.clamp
(fermeture de google) uniquement avec des tableaux et sans prendre en compte la limite inférieure.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):
https://stackoverflow.com/a/26429528/986160
la source
J'aime l'approche de Fusion, mais il y a une petite erreur. Comme ça c'est correct:
C'est aussi un peu plus rapide car il utilise la
for
boucle améliorée .À la fin, j'ai écrit ma fonction comme ceci:
Je l'ai testé avec
console.time()
et il est légèrement plus rapide que l'autre fonction.la source
improved for loop
? Les boucles inversées ne sont pas toujours une amélioration des performances..length
qu'une fois, lorsque vous déclarezi
, alors que pour cette boucle. Mais je pense que cevar i = arr.length;while (i--) {}
serait encore plus rapidewhile
. Maintenant c'est encore plus rapide.Une recherche binaire légèrement modifiée sur le tableau fonctionnerait.
la source
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".
la source
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.
la source
la source
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: /
Cela peut également être exécuté sur des non-primitives, par exemple
closest(data, 21, item => item.age)
Remplacez
find
parfindIndex
pour renvoyer l'index dans le tableau.la source
Pour rechercher deux nombres les plus proches dans le tableau
la source
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):
la source