3

I want to combine two relative paths in C#.

For example:

string path1 = "/System/Configuration/Panels/Alpha";
string path2 = "Panels/Alpha/Data";

I want to return

string result = "/System/Configuration/Panels/Alpha/Data";

I can implement this by splitting the second array and compare it in a for loop but I was wondering if there is something similar to Path.Combine available or if this can be accomplished with regular expressions or Linq?

Thanks

Ioannis
  • 2,985
  • 4
  • 25
  • 19
  • 5
    What's wrong with Path.Combine? – Kyle Alons Apr 28 '10 at 16:36
  • @Kyle Alons: @loannis want's the Combine method to recognize shared segments of the path and 'merge' them appropriately. – John Weldon Apr 28 '10 at 16:38
  • 3
    The Path.Combine would return "/System/Configuration/Panels/Alpha/Data/Panels/Alpha/Data" – Ioannis Apr 28 '10 at 16:39
  • 1
    Why do you want to combine the paths, what do they represent? What if they could be combined in more than one way? If you combine "/System/a/b/a/b" with "a/b/a/b/c", would that be "/System/a/b/a/b/c" or "/System/a/b/a/b/a/b/c"? – Guffa Apr 28 '10 at 16:50

4 Answers4

5

Provided that the two strings are always in the same format as in your example, this should work:

string path1 = "/System/Configuration/Panels/Alpha";
string path2 = "Panels/Alpha/Data";

var x = path1.Split('/');
var y = path2.Split('/');

string result = Enumerable.Range(0, x.Count())

                          .Where(i => x.Skip(i)
                                       .SequenceEqual(y.Take(x.Skip(i)
                                                              .Count())))

                          .Select(i => string.Join("/", x.Take(i)
                                                         .Concat(y)))

                          .LastOrDefault();

// result == "/System/Configuration/Panels/Alpha/Data"

For path1 = "/System/a/b/a/b" and path2 = "a/b/a/b/c" the result is "/System/a/b/a/b/a/b/c". You can change LastOrDefault to FirstOrDefault to get "/System/a/b/a/b/c" instead.


Note that this algorithm essentially creates all possible combinations of the two paths and isn't particularly efficient.

dtb
  • 213,145
  • 36
  • 401
  • 431
  • Thank you that is very elegant code. I didn't want to use for. :) – Ioannis Apr 28 '10 at 16:48
  • 1
    The caveat being that you have to *assume* that "Panels/Alpha" are the same folders as "/System/Configuration/*Panels/Alpha*" – John Weldon Apr 28 '10 at 16:49
  • 3
    I wouldn't call this elegant, in fact I think it's rather ugly. No offence to the author is intended, but if I were assigned to maintain this particular application, I would prefer that the author of written it in standard, imperative, code. It's cool code in an academic sense, however. –  Apr 28 '10 at 16:52
  • 1
    I *would* call this elegant, but I think imperative-only folks would have to learn and wrap their brain around this before being able to use it. – John Weldon Apr 28 '10 at 17:51
4

I think this requires a-priori knowledge that certain folders are the same, something you cannot safely infer from just the path (given that it's not absolute).

You'd have to write some custom logic yourself to do the combining of these paths.

John Weldon
  • 39,849
  • 11
  • 94
  • 127
  • +1: without a known anchor point, the same name doesn't necessarily mean the same folder in the hierarchy. – Ben M Apr 28 '10 at 16:41
  • Assuming that part of the value of path1 is always know (e.g. "/System/Configuration/....", it is possible. – Ioannis Apr 28 '10 at 16:45
  • @loannis, but that would require that you *know* that there is a certain amount of overlap and that your folder structure doesn't include other paths that have similar names. – John Weldon Apr 28 '10 at 16:48
0

Try this...

var p1 = path1.Split('/');
var p2 = path2.Split('/');

result = p1.Union(p1);

It uses System.Linq, and can easily be packaged into an extension method.

Of course, it assumes something about the values of path1 and path2.

pblasucci
  • 1,738
  • 12
  • 16
  • While my solution probably isn't perfect as well, this fails for a lot more cases. For example, if `path1 = "/System/Panels/Configuration/Panels/Alpha"` and `path2 = "Panels/Alpha/Data"`, the result is `"/System/Panels/Configuration/Alpha/Data"`. – dtb Apr 28 '10 at 16:52
  • Agreed... though really, its impossible to provide a "best-fit" solution without having some additional context. – pblasucci Apr 28 '10 at 16:58
0

Path.GetFullPath(Path.Combine(path1, path2))

GetFullPath will merge and simplify the resulting path.

EDIT: Never mind, that only works for absolute paths...

Steve Dennis
  • 1,343
  • 10
  • 10