3
votes

Comment utiliser LINQ pour ordonner un nom de fichier par une sous-chaîne à l'aide d'une condition?

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 commentaires

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 , le Jour et le Mois 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é!


6 Réponses :


2
votes

Pourquoi ne pas utiliser un Select où vous projetez le nom de fichier sur deux propriétés:

  • FileYear: 2018, 2019, tout jusqu'au premier trait de soulignement
  • FilePeriod: un entier où (0) = année, (1) = jour, (2) = mois, la partie après le deuxième trait de soulignement

.

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);


0 commentaires

0
votes
 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.

0 commentaires

0
votes

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);


0 commentaires

0
votes
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);
    }
}

0 commentaires

1
votes

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)});


0 commentaires

0
votes

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
)


0 commentaires