匹配不同长度的字符串前缀

Match string prefixes with different length

我正在尝试标记布尔代数,因此我需要检查 str 的开头是否与标记列表匹配(例如 ANDOR 等) . str.startsWith 在 if else 中显然会起作用,但这是一个丑陋的解决方案,所以我想知道是否有一种方法可以匹配像

这样的 str
match st {
  "OR", .. => ...
}

(显然不是真正的语法)

另外:我不能依赖字符串后面的空格或其他字符,ABxxxx 不应该匹配,而 ORxxxxx 应该匹配。

我认为如果您只需要匹配几个字符串,那么 if ... else if 树或 Martin 的解决方案可能是最好的。否则,我认为没有办法使用 match.

来匹配字符串切片前缀

但是,如果您有很多字符串需要匹配,我建议使用 AhoCorasick,这在算法上是最优的。您可以使用 aho-corasick crate.

use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};

const PATTERNS: &[&str] = &["OR", "AND"];

fn op<T: AsRef<[u8]>>(ac: &AhoCorasick, v: T) -> Option<&'static str> {
    ac.find(v).map(|m| PATTERNS[m.pattern()])
}

fn main() {
    let ac = AhoCorasickBuilder::new()
        .auto_configure(PATTERNS)
        .anchored(true)
        .match_kind(MatchKind::LeftmostFirst)
        .build(PATTERNS);
    println!(
        "{:?} / {:?} / {:?}",
        op(&ac, "OR"),
        op(&ac, "AND"),
        op(&ac, "XOR")
    )
}

使它适用于此处前缀的技巧是设置 anchored(true)。这将确保返回的任何匹配项都必须锚定到大海捞针的开头。

LeftmostFirst 匹配种类设置可能不是必需的,但它指示匹配器优先选择较早的模式而不是较晚的模式。例如,如果您的模式是 SamwiseSam,那么 LeftmostFirst 将确保 Samwise 匹配 Samwise 而不是 Sam。如果您的 none 个模式具有重叠前缀,那么您可以删除此设置。

最后,auto_configure 选项将在自动机中启用一些优化,例如,如果模式数量足够少,则使用 DFA 而不是 NFA。

See it also on the playground.