6
votes

Construire une nouvelle chaîne semblable à un chemin à partir d'une chaîne existante

Je voudrais modifier une chaîne source qui ressemble à

var folder = "one.two.three";
var folderParts = folder.Split('.');
var newFolder = new StringBuilder();
for (int i = 0; i < folderParts.Length; i++)
{
    for (int j = 0; j < i; j++)
    {
       if (j == 0)
       {
          newFolder.Append("\\");
       }

       newFolder.Append($"{folderParts[j]}.");
    }

    newFolder.Append(folderParts[i]);
}

et la transférer dans une chaîne avec des barres obliques pour l'utiliser comme une chaîne de dossier qui a la structure suivante: p>

"one\one.two\one.two.three"

Connaissez-vous des façons plus élégantes de réaliser cela que ma solution ci-dessous? Je ne suis pas très satisfait de mes boucles for.

"one.two.three" 


1 commentaires

Il y a doit être un moyen de faire cela avec Aggregate, mais je ne peux pas vraiment mettre le doigt dessus.


4 Réponses :


8
votes

Vous pouvez essayer Linq:

 one\one.two\one.two.three 

  string folder = "one.two.three";
  string[] parts = folder.Split('.');

  string result = Path.Combine(Enumerable
    .Range(1, parts.Length)
    .Select(i => string.Join(".", parts.Take(i)))
    .ToArray());

  Console.Write(newFolder);
p >


2 commentaires

Peut-être utiliser Path.Combine sur cette première string.Join , pour multiplateforme?


@ canton7: ​​Merci! Path.Combine est bien meilleur dans le contexte



9
votes

Vous pouvez le faire de manière assez laconique avec Regex

var a = "";
var newFolder = Path.Combine(folder.Split('.')
    .Select(x => a += (a == "" ? "" : ".") + x).ToArray());

Cela correspond à chaque période. Chaque fois qu'il trouve un point, il insère une barre oblique inverse puis la chaîne d'entrée entière avant la correspondance ( $ `). Nous devons ajouter le point à nouveau à la fin.

Donc, les étapes sont ( indiquent le texte inséré par la substitution à cette étape):

  1. Match sur la 1ère période. un.two.trois
  2. Match sur la 2ème période. one\one.two.three
  3. Résultat: one\one.two\one.two.three

Pour les points bonus, utilisez Path.DirectorySeparatorChar pour l'exactitude multiplateforme.

var newFolder = Regex.Replace(folder, @"\.", $"{Path.DirectorySeparatorChar}$`.")

Voici une autre méthode linqy: p>

var newFolder = Regex.Replace(folder, @"\.", @"\$`.");


4 commentaires

Agréable! Juste sur Remplacer pour obtenir le résultat


C'est, bien sûr, la solution la plus courte mais assez difficile à lire si vous n'êtes pas un geek de regex. Merci pour l'explication détaillée! :)


Merci également pour l'indication concernant la compatibilité multiplateforme.


@Christoph d'accord. J'ai dit que c'était laconique, non pas que c'était nécessairement lisible! Pour être honnête, j'écrirais un commentaire contre l'une de ces solutions en disant ce qu'elle a fait. Vous pouvez ajouter quelques lignes supplémentaires de commentaires à celui-ci expliquant comment cela fonctionne avant qu'il ne soit aussi long que la prochaine réponse test.



3
votes

Vous pouvez avancer dans une seule boucle comme ceci:

    var folder = "one.two.three";
    var newFolder = new StringBuilder();

    int index = -1;
    while (index + 1 < folder.Length) {
        index = folder.IndexOf('.', index + 1);
        if (index < 0) {
            newFolder.Append(folder);
            break;
        }
        else {
            newFolder.Append(folder, 0, index);
            newFolder.Append(Path.DirectorySeparatorChar);
        }
    }

Vous pouvez essayez-le ici .


0 commentaires

3
votes

Au lieu de diviser la chaîne en premier, je trouve plus élégant de commencer par ce que vous avez et de le réduire:

one\one.two\one.two.three 

Sortie:

XXX


0 commentaires