rust - 如何修剪少于n次的空间?

标签 rust texttrimming

如何在每行的开头消除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/

    相关文章:

    wpf - TextBlock 中的文本在 ListBox 中未正确修剪

    wpf - 组合框 TextWrap 绑定(bind)

    rust - 为什么在使用非文字模式时无法访问此匹配模式?

    php - 表单处理时如何确定post方法中的空间?

    oop - 具有 Box 字段并实现异步特征的 Rust 结构

    types - 错误[E0308] : mismatched types expected `()` ,找到了 `bool`。如何清除此错误?

    c# - 是什么决定了 WPF 中文本的修剪方式

    rust - 有条件地在Rust中对Vec进行排序

    rust - 将模块存储为 Rust 中的变量