Si j'ai deux chemins, comment puis-je trouver le chemin commun le plus long des deux?
Paths.get("/a/b/c")
Résultat attendu:
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"))
p >
3 Réponses :
Path result = path1.resolve(relativePath).normalize() // result: /a/b/c
Nous pouvons générer tous les sous-chemins à partir du plus long possible et vérifier lesquels sont égaux:
/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
Et utilisation:
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))));
Ci-dessus code imprime:
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(); }
Vous voudrez peut-être ajouter un appel à getRoot ()
pour résoudre le problème de suppression du "/" initial.
Bonne prise. Merci! J'ai mis à jour la réponse avec votre suggestion.
Essayez cette idée simple
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);
Cela semble bon, sauf si vous utilisez des chemins absolus "/ a / b / c", vous obtiendrez le chemin relatif "a / b / c".
Vous voudrez peut-être ajouter un appel getRoot ()
.
Merci @DodgyCodeException, j'ai ajouté du code pour prendre en charge les deux cas.
Maintenant, cela fonctionne bien sous Linux, mais pas sous Windows ("C: \ a \ b", "D: \ f \ g" -> "\"?)
@DodgyCodeException, belle prise. J'ai mis à jour la réponse.
Voulez-vous trouver le préfixe commun le plus long? Ou n'importe quel sous-chemin commun le plus long?
Vous pouvez diviser les chaînes et comparer les parties entre les "/". À la fin, retournez la sous-chaîne correcte.
@ MichałZiober le préfixe commun le plus long. Il doit trouver le répertoire parent le plus proche commun aux deux chemins.