2 votes

Comment trier une liste de chaînes de caractères avec un format spécifique en utilisant string.split ?

Je reçois des fichiers dont les noms de fichier ont le format suivant :

File_1242161_08112019010101PM y File_1710485_08112019111721AM .

Je dois traiter ces fichiers dans l'ordre de l'heure de la date dans la troisième section de la chaîne. Je veux également être en mesure de traiter les fichiers qui ne suivent pas ce format particulier, par exemple :

Fichier_666840

Je veux trier la liste de la date la plus ancienne à la plus récente, et s'il n'y a pas de date, aller au bas de la liste en triant par le nom du fichier. J'ai essayé ce qui suit :

List<string> sorted = filenames.OrderByDescending(file => file.Name.Split('_').Count())
                .ThenBy(file => file.Name.Split('_').LastOrDefault().ToList());

Cela me permet d'atteindre presque tout le but, mais le tri AM/PM n'est pas correct. Le nom de fichier avec 01:01:01 PM apparaîtra avant 11:17:21 AM pour des raisons évidentes. Quelle serait la façon la plus performante et la plus LINQ d'accomplir ce que je veux ?

3voto

TheGeneral Points 40470

Il suffit d'utiliser ParseExact avec le format MMddyyyyhhmmsstt et sélectionnez un ValueTuple ou quelque chose comme ça.

Convertit la représentation de la chaîne de caractères spécifiée d'une date et d'une heure en son équivalent DateTime. équivalent DateTime. Le format de la représentation de la chaîne doit correspondre exactement à un format spécifié ou une exception est levée.

<em>Puisque c'est séparé maintenant, vous pouvez commander comme vous voulez, c'est juste un exemple.</em>

Étant donné que

var list = new List<string>()
              {
                 "File_1242161_08112019010101PM",
                 "File_1710485_08112019111721AM",
                 "File_1710488",
                 "File_1710489",
                 "File_1710480"
              };

Code

var orderedList = list.Select<string, (string Value, DateTime? Date)>(
                          x =>
                             {
                                var results = x.Split('_');

                                if (results.Length < 3)
                                   return (x, (DateTime?)null);

                                return (x, DateTime.ParseExact(results[2], "MMddyyyyhhmmsstt", CultureInfo.InvariantCulture));
                             })
                      .OrderBy(x => x.Date == null)
                      .ThenBy(x => x.Date)
                      .ThenBy(x => x.Value)
                      .ToList();

Utilisation

foreach (var item in orderedList)
   Console.WriteLine(item.Value);

Résultats

File_1710485_08112019111721AM
File_1242161_08112019010101PM
File_1710480
File_1710488
File_1710489

<strong><em>Note </em></strong><em>: J'ai utilisé des tuples explicitement nommés pour plus de clarté, et vous pourriez probablement rendre cela plus succinct</em>

<strong><em>Note 2 </em></strong><em>: Quant à être performant, il existe d'autres solutions.... Cependant, à moins que vous ne décodiez des millions de fichiers, vous trouverez que l'appel pour obtenir les noms de fichiers est plus important que le coût de la routine.</em>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X