如何在每行的开头消除n个空格?
例如,当修剪4个空格时:
" 5"
-> " 5"
" 4"
-> "4"
" 3"
-> "3"
const INPUT:&str = " 4\n 2\n0\n\n 6\n";
const OUTPUT:&str = "4\n2\n0\n\n 6\n";
#[test]
fn main(){
assert_eq!(&trim_deindent(INPUT,4), OUTPUT)
}
最佳答案
我正要评论 textwrap::dedent
,但是随后我注意到"2"
,它的空格少于4个。因此,您希望它继续删除空间(如果有的话,直到4点)。
只是编写一个快速的解决方案,它可能看起来像这样:
您的断言会通过,但是请注意,以\r\n
结尾的行将转换为\n
,因为 lines
无法提供区分\n
和\r\n
的方法。
fn trim_deindent(text: &str, max: usize) -> String {
let mut new_text = text
.lines()
.map(|line| {
let mut max = max;
line.chars()
// Skip while `c` is a whitespace and at most `max` spaces
.skip_while(|c| {
if max == 0 {
false
} else {
max -= 1;
c.is_whitespace()
}
})
.collect::<String>()
})
.collect::<Vec<_>>()
.join("\n");
// Did the original `text` end with a `\n` then add it again
if text.ends_with('\n') {
new_text.push('\n');
}
new_text
}
如果要同时保留
\n
和\r\n
,则可以采用更复杂的方式扫描字符串,从而避免使用 lines
。fn trim_deindent(text: &str, max: usize) -> String {
let mut new_text = String::new();
let mut line_start = 0;
loop {
let mut max = max;
// Skip `max` spaces
let after_space = text[line_start..].chars().position(|c| {
// We can't use `is_whitespace` here, as that will skip past `\n` and `\r` as well
if (max == 0) || !is_horizontal_whitespace(c) {
true
} else {
max -= 1;
false
}
});
if let Some(after_space) = after_space {
let after_space = line_start + after_space;
let line = &text[after_space..];
// Find `\n` or use the line length (if it's the last line)
let end = line
.chars()
.position(|c| c == '\n')
.unwrap_or_else(|| line.len());
// Push the line (including the line ending) onto `new_text`
new_text.push_str(&line[..=end]);
line_start = after_space + end + 1;
} else {
break;
}
}
new_text
}
#[inline]
fn is_horizontal_whitespace(c: char) -> bool {
(c != '\r') && (c != '\n') && c.is_whitespace()
}
关于rust - 如何修剪少于n次的空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60337455/