leetcode/
simplify_path.rs

1//! # 71. 简化路径
2//!
3//! 难度 中等
4//!
5//! 以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
6//!
7//! 在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示
8//! 将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。
9//! 更多信息请参阅:[Linux / Unix中的绝对路径 vs 相对路径](https://blog.csdn.net/u011327334/article/details/50355600)
10//!
11//! 请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。
12//! 最后一个目录名(如果存在)**不能**以 / 结尾。此外,规范路径必须是表示绝对路径的**最短**字符串。
13//!
14//! ## 示例 1:
15//!
16//! ```no_run
17//! /// 输入:"/home/"
18//! /// 输出:"/home"
19//! /// 解释:注意,最后一个目录名后面没有斜杠。
20//! use leetcode::simplify_path::Solution;
21//! assert_eq!("/home", Solution::simplify_path("/home/".into()));
22//! ```
23//!
24//! ## 示例 2:
25//!
26//! ```no_run
27//! /// 输入:"/../"
28//! /// 输出:"/"
29//! /// 解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
30//! use leetcode::simplify_path::Solution;
31//! assert_eq!("/", Solution::simplify_path("/../".into()));
32//! ```
33//!
34//! ## 示例 3:
35//!
36//! ```no_run
37//! /// 输入:"/home//foo/"
38//! /// 输出:"/home/foo"
39//! /// 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
40//! use leetcode::simplify_path::Solution;
41//! assert_eq!("/home/foo", Solution::simplify_path("/home//foo/".into()));
42//! ```
43//!
44//! ## 示例 4:
45//!
46//! ```no_run
47//! /// 输入:"/a/./b/../../c/"
48//! /// 输出:"/c"
49//! use leetcode::simplify_path::Solution;
50//! assert_eq!("/c", Solution::simplify_path("/a/./b/../../c/".into()));
51//! ```
52//!
53//! ## 示例 5:
54//!
55//! ```no_run
56//! /// 输入:"/a/../../b/../c//.//"
57//! /// 输出:"/c"
58//! use leetcode::simplify_path::Solution;
59//! assert_eq!("/c", Solution::simplify_path("/a/../../b/../c//.//".into()));
60//! ```
61//!
62//! ## 示例 6:
63//!
64//! ```no_run
65//! /// 输入:"/a//b////c/d//././/.."
66//! /// 输出:"/a/b/c"
67//! use leetcode::simplify_path::Solution;
68//! assert_eq!("/a/b/c", Solution::simplify_path("/a//b////c/d//././/..".into()));
69//! ```
70//!
71//! See [leetcode](https://leetcode-cn.com/problems/simplify-path/)
72
73pub struct Solution;
74
75impl Solution {
76
77    /// 使用 `Iterator` 操作会很简单
78    pub fn simplify_path(path: String) -> String {
79        let paths = path
80            .split('/')
81            .filter(|&p| p != "." && !p.is_empty())
82            .fold(vec![], |mut acc, p| {
83                match p {
84                    ".." => drop(acc.pop()),
85                    p => acc.push(p),
86                }
87                acc
88            })
89            .join("/");
90
91        "/".to_string() + &paths
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn test() {
101        let t = |p: &str| Solution::simplify_path(p.into());
102        assert_eq!("/",         t("/../"));
103        assert_eq!("/home/foo", t("/home//foo/"));
104        assert_eq!("/c",        t("/a/./b/../../c/"));
105        assert_eq!("/c",        t("/a/../../b/../c//.//"));
106        assert_eq!("/a/b/c",    t("/a//b////c/d//././/.."));
107    }
108}