如何修剪少于n次的空间



如何消除每行开头最多n个空格?

例如,当修剪4个空间时:

  • " 5"->" 5"
  • " 4"->"4"
  • " 3"->"3"
const INPUT:&str = "    4n  2n0nn      6n";
const OUTPUT:&str = "4n2n0nn  6n";
#[test]
fn main(){
assert_eq!(&trim_deindent(INPUT,4), OUTPUT)
}

我正要评论textwrap::dedent,但后来我注意到"2",它的空格不到4个。所以你希望它继续删除空格,如果有的话,直到4。

只要写一个快速的解决方案,它可能看起来像这样:

您的断言将通过,但请注意,以rn结尾的行将转换为n,因为lines没有提供区分nrn的方法。

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
}

如果您想同时保留nrn,那么您可以采用更复杂的方法扫描字符串,从而避免使用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()
}

最新更新