Christoph Brückmann
Christoph Brückmann

Reputation: 1373

Building a new path-like string from an existing one

I'd like to modify a source string which is looking like

"one.two.three" 

and transfer it into a string with slashes to use it as a folder string which has the following structure:

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

Do you know more elegant ways to realize this, than my solution below? I'm not very satisfied with my for-loops.

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

Upvotes: 6

Views: 276

Answers (4)

canton7
canton7

Reputation: 42225

You can do this quite tersely with Regex

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

This matches on each period. Each time it finds a period, it inserts a backslash and then the entire input string before the match ($`). We have to add the period in again at the end.

So, steps are (< and > indicate text inserted by the substitution at that step):

  1. Match on the 1st period. one<\one>.two.three
  2. Match on the 2nd period. one\one.two<\one.two>.three
  3. Result: one\one.two\one.two.three

For bonus points, use Path.DirectorySeparatorChar for cross-platform correctness.

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

Here's another linqy way:

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

Upvotes: 9

sebrockm
sebrockm

Reputation: 6002

Instead of splitting the string first, I find it more elegant to start with what you have and reduce it:

var folder = "one.two.three";
var newFolder = string.Empty;
for (var f = folder; f.Any(); f = f.Remove(Math.Max(f.LastIndexOf('.'), 0)))
    newFolder = Path.Combine(f, newFolder);

Console.WriteLine(newFolder);

Output:

one\one.two\one.two.three 

Upvotes: 3

Sefe
Sefe

Reputation: 14007

You can go forward-only in one loop like this:

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

You can try it out here.

Upvotes: 3

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

You can try Linq:

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

Outcome:

 one\one.two\one.two.three 

Upvotes: 8

Related Questions