Simplify Path

[Simplify Path]

Given an absolute path for a file (Unix-style), simplify it.

For example,
path = "/home/", => "/home"
path = "/a/./b/../../c/", => "/c"

Corner Cases:

  • Did you consider the case where path = "/../"?
    In this case, you should return "/".
  • Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".
    In this case, you should ignore redundant slashes and return "/home/foo".

[Analysis]

The idea is straightforward if ever you think of a stack: pop if we have “..”, nothing if we have “.”, push otherwise.

The interesting part is how to split in c++. There are various ways to do it and the most interesting and most reusable way is to create a separate function to handle this task (I’m jealous of Python at this point :P). It’s a tiny bit slower since we need to go through the path twice, but we are still in O(n) and the gain in reusability wins in my book. Credit to Stackoverflow for the split solution.

vector split(const string &s, char delim) {
    vector elems;
    stringstream ss(s);
    string item;
    // getLine stops at the next delim and put everything before that into item.
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

string simplifyPath(string path) {
    stack directories;

    vector path_v = split(path, '/');

    string simplePath;

    for (auto s : path_v) {
        if (s.empty()) continue;
        if (s == ".." && !directories.empty())
            directories.pop();
        if (s!= ".." && s != ".")
            directories.push(s);
    }

    while (!directories.empty()){
        simplePath = "/"+directories.top() + simplePath;
        directories.pop();
    }

    if (simplePath.empty())
        simplePath += "/";

    return simplePath;
}

Leave a comment