int[] array = new int[5]{5,7,8,15,20};
int TargetNumber = 13;
Pour un nombre cible, je veux trouver le nombre le plus proche dans un tableau. Par exemple, lorsque le nombre cible est 13, le nombre le plus proche dans le tableau ci-dessus est 15. Comment pourrais-je accomplir cela par programme en C #?
Si vous utilisez .Net 3.5 ou supérieur, LINQ peut vous aider ici:
var closest = array.OrderBy(v => Math.Abs((long)v - targetNumber)).First();
Alternativement, vous pouvez écrire votre propre méthode d'extension:
public static int ClosestTo(this IEnumerable<int> collection, int target)
{
// NB Method will return int.MaxValue for a sequence containing no elements.
// Apply any defensive coding here as necessary.
var closest = int.MaxValue;
var minDifference = int.MaxValue;
foreach (var element in collection)
{
var difference = Math.Abs((long)element - target);
if (minDifference > difference)
{
minDifference = (int)difference;
closest = element;
}
}
return closest;
}
Utilisable comme tel:
var closest = array.ClosestTo(targetNumber);
Jon et Rich ont tous deux donné d'excellentes réponses avec MinBy
et ClosestTo
. Mais je ne recommanderais jamais d'utiliser OrderBy
si votre intention est de trouver un seul élément. C'est beaucoup trop inefficace pour ce genre de tâches. C'est simplement le mauvais outil pour le travail.
Voici une technique qui fonctionne légèrement mieux que MinBy, est déjà incluse dans le framework .NET mais moins élégante que MinBy: Aggregate
var nearest = array.Aggregate((current, next) => Math.Abs((long)current - targetNumber) < Math.Abs((long)next - targetNumber) ? current : next);
Comme je l'ai dit, pas aussi élégante que la méthode de Jon, mais viable.
Performance sur mon ordinateur:
J'ai trouvé cette approche très sexy il y a des années dans Math.NET Numerics https://numerics.mathdotnet.com/ qui fonctionne avec BinarySearch dans le tableau. Ce fut une bonne aide pour la préparation des interpolations et passe à .Net 2.0:
public static int LeftSegmentIndex(double[] array, double t)
{
int index = Array.BinarySearch(array, t);
if (index < 0)
{
index = ~index - 1;
}
return Math.Min(Math.Max(index, 0), array.Length - 2);
}
Le code personnalisé sage de performance sera plus utile.
public static int FindNearest(int targetNumber, IEnumerable<int> collection) {
var results = collection.ToArray();
int nearestValue;
if (results.Any(ab => ab == targetNumber))
nearestValue = results.FirstOrDefault(i => i == targetNumber);
else{
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > targetNumber)) {
greaterThanTarget = results.Where(i => i > targetNumber).Min();
}
if (results.Any(ab => ab < targetNumber)) {
lessThanTarget = results.Where(i => i < targetNumber).Max();
}
if (lessThanTarget == 0) {
nearestValue = greaterThanTarget;
}
else if (greaterThanTarget == 0) {
nearestValue = lessThanTarget;
}
else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber) {
nearestValue = lessThanTarget;
}
else {
nearestValue = greaterThanTarget;
}
}
return nearestValue;
}
Si vous avez besoin de trouver la valeur la plus proche de la moyenne
public static double Miidi(double[] list)
{
bool isEmpty = !list.Any();
if (isEmpty)
{
return 0;
}
else
{
double avg = list.Average();
double closest = 100;
double shortest = 100;
{
for ( int i = 0; i < list.Length; i++)
{
double lgth = list[i] - avg;
if (lgth < 0)
{
lgth = lgth - (2 * lgth);
}
else
lgth = list[i] - avg;
if (lgth < shortest)
{
shortest = lgth;
closest = list[i];
}
}
}
return closest;
}
}