views:

157

answers:

4

Given an input string, I would like to get the output from this in the specified format: filename;path.

For the input string /vob/TEST/.@@/main/ch_vobsweb/1/VOBSWeb/main/ch_vobsweb/4/VobsWebUI/main/ch_vobsweb/2/VaultWeb/main/ch_vobsweb/2/func.js

I expect this output string: func.js;VOBSWeb/VosWebUI/VaultWeb/func.js

The filename is listed at the end of the whole string, and its path is supposed to be stripped using the characters after each numeric value (eg. /1/VOBSWeb/ and then /4/VobsWebUI and then /2/vaultWeb)

A: 

.NET 2.0 solution

static void ParseFilePath(string text, out string file, out string path)
{
    string[] tokens = text.Split('/');
    file = tokens[tokens.Length - 1];
    path = String.Empty;
    string last = String.Empty;

    foreach (var token in tokens)
    {
        if (Regex.IsMatch(last, @"^\d+$"))
            path += path == String.Empty ? token : @"\" + token;
        last = token;
    }
}

.NET 3.5 solution

static void ParseFilePath(string text, out string file, out string path)
{
    var result = (from token in Regex.Split(text, @"/\d+/")
                  let folder = token.Split('/').First()
                  select folder).Skip(1).ToArray();
    path = String.Join("/", result);
    file = result.Last();
}
Hasan Khan
I called this inefficient because, among other things, it uses a regexp that needs to be reinterpreted over and over again inside a loop. If I were to use a regexp, I would define a *compiled* regexp and reuse it.
Steven Sudit
This is unmaintainable for a few reasons. One is that is already has bugs; try passing in an empty `text` and watch it crash. Another is that, for all their flexibility, regexp's are generally quite hard to understand and maintain, unless every developer is a grep-head.
Steven Sudit
Finally, four people have questioned your strategy of providing a fully-working solution instead of helping the OP debug theirs.
Steven Sudit
How sweet. I think I just had to give a solution; not validate inputs and throw exceptions on arguments. You're being impractical. This is not a classroom; its a QA site. Either you answer the question or stay back.
Hasan Khan
I reserve the right to comment on suggested answers.
Steven Sudit
Even if you have a solution it is not an bad idea to post it on a forum ,if it helps others , who know's it can be better than theirs.Thank you guys
Raj
A: 

Javascript has a split() function on strings that returns an array, so I think that's probably a good starting point for what you're going for.

Joe Enos
FYI: This question used to have a javascript tag, not a C# tag, before it was merged.
Joe Enos
Wanted to have the same sortedout in Javascript if possible
Raj
A: 

Assuming its not an arbitrary number of paths you can use regular expressions:

Find this:

.*[0-9]/([a-zA-Z]*)/[^0-9]*[0-9]/([a-zA-Z]*)/[^0-9]*[0-9]/([a-zA-Z]*)/[^0-9]*[0-9]/([a-zA-Z.]*)/

Then use the groupings to write the new string:

\4;\1/\2/\3/\4
Javid Jamae
+1  A: 

If the number of paths is arbitrary, then you need a two-step approach:


First, remove all the "uninteresting stuff" from the string.

Search for .*?/\d+/([^/]+/?) and replace all with $1.

In C#: resultString = Regex.Replace(subjectString, @".*?/\d+/([^/]+/?)", "$1");

In JavaScript: result = subject.replace(/.*?\/\d+\/([^\/]+\/?)/g, "$1");

This will transform your string into VOBSWeb/VobsWebUI/VaultWeb/func.js.


Second, copy the filename to the front of the string.

Search for (.*/)([^/]+)$ and replace with $2;$1$2.

C#: resultString = Regex.Replace(subjectString, "(.*/)([^/]+)$", "$2;$1$2");

JavaScript: result = subject.replace(/(.*\/)([^\/]+)$/g, "$2;$1$2");

This will transform the result of the previous operation into func.js;VOBSWeb/VobsWebUI/VaultWeb/func.js


If the number of paths is constant, then you can do it in a single regex:

Search for ^.*?/\d+/([^/]+/).*?/\d+/([^/]+/).*?/\d+/([^/]+/).*?/\d+/([^/]+)

and replace with $4;$1$2$3$4.

C#: resultString = Regex.Replace(subjectString, @"^.*?/\d+/([^/]+/).*?/\d+/([^/]+/).*?/\d+/([^/]+/).*?/\d+/([^/]+)", "$4;$1$2$3$4");

JavaScript: result = subject.replace(/^.*?\/\d+\/([^\/]+\/).*?\/\d+\/([^\/]+\/).*?\/\d+\/([^\/]+\/).*?\/\d+\/([^\/]+)/g, "$4;$1$2$3$4");

This regex will be inefficient if the string fails to match; this could be improved with atomic grouping, but JavaScript doesn't support that.

Tim Pietzcker