Найдите самый длинный путь, общий для двух путей в Java - PullRequest
0 голосов
/ 08 февраля 2019

Если у меня есть два пути, как мне найти самый длинный общий путь из двух?

import java.nio.file.Path;
import java.nio.file.Paths;

Path common(Path pathA, Path pathB) {
    ...
}
...
common(Paths.get("/a/b/c/d/e"), Paths.get("/a/b/c/g/h"))

Ожидаемый результат:

Paths.get("/a/b/c")

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Мы можем сгенерировать все подпути, начиная с самого длинного из возможных, и проверить, какие из них равны:

private Path commonPath(Path path0, Path path1) {
    if (path0.equals(path1)) {
        return path0;
    }

    path0 = path0.normalize();
    path1 = path1.normalize();
    int minCount = Math.min(path0.getNameCount(), path1.getNameCount());
    for (int i = minCount; i > 0; i--) {
        Path sp0 = path0.subpath(0, i);
        if (sp0.equals(path1.subpath(0, i))) {
            String root = Objects.toString(path0.getRoot(), "");
            return Paths.get(root, sp0.toString());
        }
    }

    return path0.getRoot();
}

И использование:

Map<String, String> paths = new LinkedHashMap<>();
paths.put("/a/b/c", "/a/b/d");
paths.put("/a/", "/a/b/d");
paths.put("/f/b/c", "/a/b/d");
paths.put("/a/b/c/d/e", "/a/b/f/../c/g");
paths.put("C:/Winnt/System32", "C:/Winnt/System64");

paths.forEach((k, v) ->
        System.out.println(
                k + " = " + v + " => " + commonPath(Paths.get(k), Paths.get(v))));

Над отпечатками кода:

/a/b/c = /a/b/d => /a/b
/a/ = /a/b/d => /a
/f/b/c = /a/b/d => /
/a/b/c/d/e = /a/b/f/../c/g => /a/b/c
C:/Winnt/System32 = C:/Winnt/System64 => C:/Winnt
0 голосов
/ 08 февраля 2019

Попробуйте эту простую идею

    Path a = Paths.get("a/b/c/d/e");
    Path b = Paths.get("a/b/c/g/h");

    // Normalize
    a = a.normalize();
    b = b.normalize();

    // Create common root
    Path common = null;
    if (a.isAbsolute() && b.isAbsolute() && a.getRoot().equals(b.getRoot())) {
            common = a.getRoot();
    }
    else if (!a.isAbsolute() && !b.isAbsolute()) {
            common = Paths.get("");
    }

    // Iterate from root until names differ
    if (common != null) {
            int n = Math.min(a.getNameCount(), b.getNameCount());
            for (int i=0; i<n; i++) {
                    if (a.getName(i).equals(b.getName(i))) {
                            common = common.resolve(a.getName(i));
                    }
                    else {
                            break;
                    }
            }
    }

    // Show
    System.out.println(common);
0 голосов
/ 08 февраля 2019
Path path1 = Paths.get("/a/b/c/d/e");
Path path2 = Paths.get("/a/b/c/g/h");

Вы можете релятивизировать пути друг к другу:

Path relativePath = path1.relativize(path2).normalize();
// result: ../../g/h

и затем переходить к родителю, пока путь не заканчивается в ..

while(relativePath != null && !relativePath.endsWith("..")) {
    relativePath = relativePath.getParent();
}
// result: ../.. (but may also be null)

результат можетприменить обратно к любому из двух путей:

Path result = path1.resolve(relativePath).normalize()
// result: /a/b/c
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...