matchsorter
Fuzzy string matching and sorting for Rust, inspired by Kent C. Dodds' match-sorter for JavaScript.
Overview
matchsorter ranks candidate strings against a search query using an 8-tier
ranking system, then returns them sorted from best to worst match. It handles
everything from exact equality down to fuzzy character-by-character matching,
with optional diacritics normalization, key extraction for structs, and
per-key ranking controls.
Key differences from the JS library:
- Native Rust performance (5-8x faster on equivalent workloads)
- Zero-copy ranking in no-keys mode (borrows directly from input)
- SIMD-accelerated substring search via
memchr - Amortized allocations through reusable buffers and
PreparedQuery
Quick Start
Add to your Cargo.toml:
use ;
let items = ;
let results = match_sorter;
assert_eq!;
Ranking Tiers
Every candidate is classified into one of 8 tiers, checked in order from best to worst. The first matching tier is used.
| Tier | Name | Example (query "app") |
|---|---|---|
| 7 | CaseSensitiveEqual | "app" matches "app" exactly |
| 6 | Equal | "app" matches "APP" (case-insensitive) |
| 5 | StartsWith | "app" matches "apple" |
| 4 | WordStartsWith | "app" matches "pine apple" (word boundary) |
| 3 | Contains | "app" matches "pineapple" (substring) |
| 2 | Acronym | "nwa" matches "North-West Airlines" |
| 1..2 | Matches | "plgnd" fuzzy-matches "playground" |
| 0 | NoMatch | No match found |
Features
- 8-tier ranking from exact match to fuzzy character matching
- Diacritics normalization --
"cafe"matches"cafe"by default (toggle withkeep_diacritics) - Key extraction -- match against struct fields with
Key::new,Key::from_fn, orKey::from_fn_multi - Per-key controls --
threshold,min_ranking, andmax_rankingper key - Custom sorting -- replace the tiebreaker (
base_sort) or the entire sort (sorter) - Zero-copy no-keys mode --
&str,String, andCow<str>work out of the box viaAsMatchStr
Advanced Usage
Keys mode with structs
use ;
use Key;
// Required for compilation; unused in keys mode.
let users = vec!;
let opts = MatchSorterOptions ;
let results = match_sorter;
assert_eq!;
Custom threshold
use ;
let items = ;
let opts = MatchSorterOptions ;
// Only items with a Contains ranking or better are returned.
// Fuzzy-only matches are excluded.
let results = match_sorter;
assert_eq!; // "apple" (Contains) and "playground" (StartsWith)
Per-key clamping
use ;
use Key;
let items = vec!;
let opts = MatchSorterOptions ;
let results = match_sorter;
assert_eq!;
Performance
Benchmarked against the JS match-sorter library (Node.js v22) on 10,000
items. All times are median microseconds.
| Benchmark | Rust | JS | Speedup |
|---|---|---|---|
| Throughput (10k items) | 481 us | 2,717 us | 5.6x |
| Exact match | 380 us | 2,092 us | 5.5x |
| Prefix match | 328 us | 2,224 us | 6.8x |
| Substring match | 390 us | 2,113 us | 5.4x |
| Fuzzy match | 495 us | 2,896 us | 5.9x |
| No match (early exit) | 359 us | 1,870 us | 5.2x |
See bench-compare/ for reproduction instructions.
License
Licensed under either of
at your option.