Trouver le temps le plus proche d’une liste de fois

Alors, voici le scénario. J’ai un fichier avec une heure créée et je veux choisir une heure parmi une liste de fois où l’heure de création de ce fichier est la plus proche ou égale aussi … quel serait le meilleur moyen d’y parvenir?

Quelque chose comme ça:

DateTime fileDate, closestDate; ArrayList theDates; long min = long.MaxValue; foreach (DateTime date in theDates) if (Math.Abs(date.Ticks - fileDate.Ticks) < min) { min = Math.Abs(date.Ticks - fileDate.Ticks); closestDate = date; } 
 var closestTime = listOfTimes.OrderBy(t => Math.Abs((t - fileCreateTime).Ticks)) .First(); 

Si vous ne voulez pas la surcharge de performance de l’appel OrderBy vous pouvez utiliser à la place quelque chose comme la méthode d’extension MoreLINQ de MoreLINQ :

 var closestTime = listOfTimes.MinBy(t => Math.Abs((t - fileCreateTime).Ticks)); 

La réponse acceptée est complètement fausse. Ce que vous voulez, c’est quelque chose comme ça:

  DateTime fileDate, closestDate; List theDates; fileDate = DateTime.Today; //set to the file date theDates = new List(); //load the date list, obviously long min = Math.Abs(fileDate.Ticks - theDates[0].Ticks); long diff; foreach (DateTime date in theDates) { diff = Math.Abs(fileDate.Ticks - date.Ticks); if (diff < min) { min = diff; closestDate = date; } } 
 var closestTime = (from t in listOfTimes orderby (t - fileInfo.CreationTime).Duration() select t).First(); 

À quelle fréquence ferez-vous cela avec la même liste de fois? Si vous ne le faites qu’une fois, le moyen le plus rapide est probablement de parcourir la liste et de garder une trace du temps le plus proche que vous ayez vu jusqu’à présent. Lorsque / si vous rencontrez un temps plus proche, remplacez le “plus proche” par ce temps plus proche.

Si vous le faites très souvent, vous voudrez probablement sortinger la liste, puis utilisez une recherche binary.

obtenez la différence de votre fichier creatime et à chaque fois dans votre liste et sortingez la valeur absolue de chaque différence de temps. le premier devrait être la réponse que vous recherchez.

Utilisez la différence de temps absolu minimum entre l’heure du fichier et l’heure de la liste. Vous pouvez obtenir 2 entrées identiques, puis vous aurez besoin d’une méthode différente pour les différencier.

Pas une réponse, mais une question concernant les différentes solutions LINQ proposées ci-dessus. Quelle est l’efficacité de LINQ? Je n’ai pas encore écrit de “vrais” programmes avec LINQ, je ne suis donc pas sûr de la performance.

Dans cet exemple, la collection “listOfTimes” implique que nous avons déjà itéré sur certains objects basés sur le système de fichiers pour rassembler les heures. Aurait-il été plus efficace de faire l’parsing lors de l’itération plutôt que plus tard dans LINQ? Je reconnais que ces solutions sont peut-être plus “élégantes” ou joliment abstraites l’idée de “collection en tant que firebase database”, mais j’ai tendance à préférer l’efficacité (bien qu’elle soit lisible) à l’élagance dans ma programmation. Vous vous demandez simplement si le coût de LINQ pourrait l’emporter sur l’élégance?

 var creationTimes = new [] {DateTime.Now.AddDays(-1), DateTime.Now.AddDays(-2)}; FileInfo fi = new FileInfo("C:/test.xml"); var closestTime = creationTimes .OrderBy(c => Math.Abs(c.Subtract(fi.CreationTime).Days)) .First(); 
 var min = listoftimes.Select( x => new { diff = Math.Abs((x - timeoffile).Ticks), time = x}). OrderBy(x => x.diff). First().time; 

Remarque: Supposons au moins 1 entrée dans listoftimes .

Je pensais mettre à jour ce post pour inclure un scénario du monde réel. Je voulais ce genre de fonction car j’ai un blog qui présente des nouvelles des dernières projections de films.

Cependant, je ne veux pas faire de liste de filtrage dans le passé (c.-à-d. Une date de filtrage au-delà de la date actuelle) et comme je voulais montrer un enregistrement, j’avais besoin d’une sorte de pièce d’identité pour le récupérer.

Je suis parti si simple pour que vous puissiez suivre le processus et le rendre sans doute plus efficace avec LINQ et al.

D’abord le modèle

  public class LatestScreeeningsModel { public int Id { get; set; } public DateTime Date { get; set; } } 

Ensuite, le bloc de code que vous pouvez appeler depuis votre contrôleur

  private static LatestScreeeningsModel GetLatestScreening(IPublishedContent currentNode) { LatestScreeeningsModel latestScreening = new LatestScreeeningsModel(); DateTime fileDate; // get a list of screenings that have not shown yet var screenings = currentNode.AncestorsOrSelf("siteLanguage") .FirstOrDefault().Descendants("screening") .Select(x => new LatestScreeeningsModel() { Id = x.Id, Date = x.GetPropertyValue("date") }) .Where(x => x.Date > DateTime.Now).ToList(); fileDate = DateTime.Today; long min = Math.Abs(fileDate.Ticks - screenings[0].Date.Ticks); long diff; foreach (var comingDate in screenings) { diff = Math.Abs(fileDate.Ticks - comingDate.Date.Ticks); if (diff <= min) { min = diff; latestScreening = comingDate; } } return latestScreening; } 

J'utilise Umbraco pour obtenir les éléments de date mais cela fonctionnerait avec n'importe quel modèle personnalisé, List et al.

J'espère que ça aide