在忽略大小写的情况下比较字符串的有效方法是什么?

Tho*_* S. 7 string case-insensitive rust

要比较两个Strings,忽略大小写,看起来我首先需要转换为字符串的小写版本:

let a_lower = a.to_lowercase();
let b_lower = b.to_lowercase();
a_lower.cmp(&b_lower)
Run Code Online (Sandbox Code Playgroud)

是否有一种方法可以比较字符串,忽略大小写,而不创建临时小写字符串,即迭代字符,执行小写转换并比较结果?

Ibr*_*med 6

如果您仅使用 ASCII,则可以使用eq_ignore_ascii_case

assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
Run Code Online (Sandbox Code Playgroud)

  • 这正是我所需要的。我正在将一组常量 ASCII 字符串与用户输入的任何内容进行比较,因此如果这不是 ASCII,那么无论如何它都不会匹配。 (2认同)

Pet*_*all 4

没有内置方法,但假设您只关心 ASCII 输入,您可以编写一个方法来完全按照您所描述的方式执行操作。

use itertools::{EitherOrBoth::*, Itertools as _}; // 0.9.0
use std::cmp::Ordering;

fn cmp_ignore_case_ascii(a: &str, b: &str) -> Ordering {
    a.bytes()
        .zip_longest(b.bytes())
        .map(|ab| match ab {
            Left(_) => Ordering::Greater,
            Right(_) => Ordering::Less,
            Both(a, b) => a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase()),
        })
        .find(|&ordering| ordering != Ordering::Equal)
        .unwrap_or(Ordering::Equal)
}
Run Code Online (Sandbox Code Playgroud)

正如下面的一些评论所指出的,如果不对整个字符串进行操作,不区分大小写的比较对于 UTF-8 将无法正常工作,即使如此,某些大小写转换也有多种表示形式,这可能会产生意外的结果。

考虑到这些注意事项,与上面的 ASCII 版本相比,以下内容将适用于许多额外情况(例如,最重音的拉丁字符),并且可能会令人满意,具体取决于您的要求:

fn cmp_ignore_case_utf8(a: &str, b: &str) -> Ordering {
    a.chars()
        .flat_map(char::to_lowercase)
        .zip_longest(b.chars().flat_map(char::to_lowercase))
        .map(|ab| match ab {
            Left(_) => Ordering::Greater,
            Right(_) => Ordering::Less,
            Both(a, b) => a.cmp(&b),
        })
        .find(|&ordering| ordering != Ordering::Equal)
        .unwrap_or(Ordering::Equal)
}
Run Code Online (Sandbox Code Playgroud)

  • 任何使用 str::chars 的方法都无法正确比较 unicode 字符串。 (3认同)
  • 如今,“假设您只关心 ASCII 输入”是非常糟糕的做法。 (2认同)