J'ai des fichiers Excel (.xlsx) dans un dossier et ses sous-dossiers que j'essaie de lister sur mon site Web. Les noms de fichiers ont le format suivant:
var fileGroup = ( from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories) let fileName = Path.GetFileName(file) orderby fileName descending select fileName ).OrderBy(f => f.Substring(f.LastIndexOf("_")))
Remarque: Jour
, Mois
et Année code > sont du texte, pas un espace réservé pour un jour, un mois ou une année numérique réel (au cas où cela serait trompeur).
J'ai besoin d'afficher ces noms de fichiers avec un nom de fichier décroissant, mais regroupés par Année
, Jour
ou Mois
dans cet ordre spécifique. Ainsi, la sortie, en utilisant la liste ci-dessus, devrait être:
2019_MyData_Year.xlsx 2018_MyData_Year.xlsx 2019_MyData_Day.xlsx 2018_MyData_Day.xlsx 2019_MyData_Month.xlsx 2018_MyData_Month.xlsx
J'ai utilisé ce qui suit pour trier le nom du fichier par année et par Jour
, Month
, Year
sous-chaîne, mais la sous-chaîne n'est pas ordonnée correctement:
2018_MyData_Day.xlsx 2018_MyData_Month.xlsx 2018_MyData_Year.xlsx 2019_MyData_Day.xlsx 2019_MyData_Month.xlsx 2019_MyData_Year.xlsx
Je suis sûr que j'ai besoin d'un condition car l'ordre souhaité est personnalisé, mais je ne sais pas comment l'implémenter.
Est-ce encore possible ou y a-t-il un meilleur moyen d'obtenir le résultat souhaité?
Merci !
6 Réponses :
Pourquoi ne pas utiliser un Select où vous projetez le nom de fichier sur deux propriétés:
.
var underscore = new char[] {'_'}; var orderedFiles = originalFiles.Select(fileName => { // TODO: decide what to do if filename incorrect format var splitFileName = fileName.Split(underscore); int filePeriod; switch (splitFileName[2]) { case "Year": filePeriod = 0; break; case "Day": filePeriod = 1; break; case "Month": filePeriod = 2; break; default: filePeriod = 3; break; } return new { FileYear = Int32.Parse(splitFileName[0]), FilePeriod = filePeriod, OriginalFileName = fileName, }; }) // sort: .OrderBy(splitFile => splitFile.FileYear) .ThenBy(splitFile => splitFile.FilePeriod) // back to original filename .Select(splitFile => splitFile.OriginalFileName);
var fileGroup = (from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories) let fileName = Path.GetFileName(file) select fileName) .GroupBy(f => f.Substring(f.LastIndexOf("_") + 1)) .Select(x => x.OrderBy(y => y)); I Think this might solve your problem.
Vous pouvez facilement le faire en utilisant certains let:
var fileGroup = (from f in Directory.GetFiles(myPath, "201*.xlsx") let fName = Path.GetFileNameWithoutExtension(f) let ymd = fName.Substring("2000_MyData_".Length).ToLower() let fOrder = (ymd == "year" ? 0 : ymd == "day" ? 1 : 2) select new {f, year=int.Parse(fName.Substring(0,4)), o=fOrder}) .OrderBy(g => g.o) .ThenByDescending(g => g.year) .Select(g => g.f);
IEnumerable<string> files = Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories).Select(x => Path.GetFileName(x)); Regex reg = new Regex(".*_(?<dmy>Day|Month|Year)\\.xlsx"); var groups = files.GroupBy(x => reg.Match(x).Groups["dmy"].Value); StringBuilder builder = new StringBuilder(); foreach (var g in groups.OrderBy(x => x.Key == "Year" ? 0 : x.Key == "Day" ? 1 : 2)) { builder.AppendLine(); foreach(var f in g.OrderByDescending(x => x)) { builder.AppendLine(f); } }
Vous pouvez utiliser LINQ comme suit.
var list = new []{ "2018_MyData_Day.xlsx", "2018_MyData_Month.xlsx", "2018_MyData_Year.xlsx", "2019_MyData_Day.xlsx", "2019_MyData_Month.xlsx", "2019_MyData_Year.xlsx" }; var result = list.GroupBy(x=> new { Type= x.Split(new[]{"_"},StringSplitOptions.RemoveEmptyEntries)[2]}) .Select(x=> new {Key = x.Key, FullName = x.OrderBy(c => c)});
vous pouvez essayer de changer votre code pour devenir:
var fileGroup = ( from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories) let fileName = Path.GetFileName(file) let fileParts = fileName.Split('.')[0].Split('_') orderby fileParts[2] descending, fileParts[0] descending select fileName )
Tout d'abord, vous devez regrouper votre "chaîne" comme vous l'avez écrit en question et votre code ne regroupe pas votre collection.
Donc _year, _month et _day sont des suffixes fixes dans le nom de fichier (je ne suis pas sûr si j'ai bien compris)? Si c'est le cas, vous pouvez diviser les fichiers en trois listes et les classer ==> filelist.Where (i => i.EndsWith ("_ year"). OrderByDescending (i => i);
@ MichałK. - Je pense que c'est avec ça que j'ai du mal. Je ne sais pas comment regrouper l '
Année
, leJour
et leMois
dans cet ordre spécifique.@Martin - Oui, "_Year", "_Day" et "_Month" sont des suffixes de texte fixes. Le nom du fichier est exactement tel qu'il apparaît dans la question, par opposition à quelque chose comme "2019_MyData_2012.xlsx". Pour votre suggestion, je devrais écrire trois déclarations distinctes, n'est-ce pas? J'espérais faire cela en une seule déclaration, si possible.
@ user2063351 Voir ma réponse alors :)
@ user2063351 est-ce que l'une des réponses vous a fourni une réponse?, si oui, veuillez la marquer :) J'espère que nous vous avons aidé!