【问题标题】:How to check if a string contains whitespace?如何检查字符串是否包含空格?
【发布时间】:2020-10-14 20:28:28
【问题描述】:

如何检查一个字符串是否包含 Rust 中的任何空格?

例如,这些都应该返回 true:

  • "Hello, world!"
  • "Hello\n"
  • "This\tis\ta\ttab"

【问题讨论】:

    标签: string rust


    【解决方案1】:

    您可以将char::is_whitespace 传递给.contains()

    assert!("Hello, world!".contains(char::is_whitespace));
    assert!("Hello\n".contains(char::is_whitespace));
    assert!("This\tis\ta\ttab".contains(char::is_whitespace));
    

    如果字符具有 Unicode White_Space 属性,则char::is_whitespace 返回 true。

    或者,如果您只想匹配 ASCII 空格(空格、水平制表符、换行符、换页或回车),您可以使用 char::is_ascii_whitespace

    // This has a non-breaking space, which is not ASCII.
    let string = "Hello,\u{A0}Rust!\n";
    
    // Thus, it's *not* ASCII whitespace
    assert!(!string.contains(char::is_ascii_whitespace));
    // but it *is* Unicode whitespace.
    assert!(string.contains(char::is_whitespace));
    

    【讨论】:

    • 如果您只检查 ASCII 空格,那么逐字节检查可能会更快:string.as_bytes().iter().any(u8::is_ascii_whitespace)
    • 为什么会明显更快?
    • 使用带有char的闭包调用.contains(...)意味着遍历所有Unicode代码点,包括多字节代码点,将每个多字节序列转换为char并调用is_ascii_whitespace在上面。其中很多都可以优化掉,而且确实如此,但是当您只要求编译器查找属于有限集合之一的所有字节时,它会使编译器的事情变得更容易。 You can compare the generated assembly code; u8::is_ascii_whitespace 大约是 char::is_ascii_whitespace 大小的四分之一(这是带有完整优化)。
    • 当您遍历字节以查找 ASCII 字符时,您不必担心多字节序列,因为0..=127 范围内的字节永远不会出现在其中。这样代码可以写得更简单。理论上编译器可以知道这一点并根据该假设进行优化,但实际上它不会。
    【解决方案2】:

    正如有人提到的,如果你不需要处理 Unicode,它会更快 只需明确命名您关心的角色:

    fn main() {
       let a = vec!["false", "true space", "true newline\n", "true\ttab"];
       let a2: &[char] = &[' ', '\n', '\t'];
    
       for s in a.iter() {
          let b = s.contains(a2);
          println!("{}", b);
       }
    }
    

    【讨论】:

    • 我认为这不会更快。他们的意思是,如果您只寻找 ASCII 空格,在字节数组上调用 .contains() 可能会更快:string.as_bytes().iter().any(u8::is_ascii_whitespace)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2012-07-14
    • 2021-08-17
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多