str::split_whitespace¶
Level: reference · for working programmers
One line: Splits on runs of Unicode whitespace and drops the empties — the editorial split, for prose and hand-typed input.
Stable since 1.1.0.
Unlike split(' '), this collapses consecutive whitespace and trims the ends, so it never yields an empty piece. " a b ".split_whitespace() is ["a", "b"], where split(' ') gives seven items, four of them empty.
Trimming first is the half-fix, and it is the one people reach for once the empties show up: .trim() takes the four off the ends of that string and leaves the four in the middle, so twelve pieces become eight where the answer is four. Runs are the harder half, and collapsing them is the whole of what this method adds over trim().split(' ').
Whitespace means char::is_whitespace — the Unicode definition, which includes tabs, newlines, non-breaking space and a dozen others. split_ascii_whitespace is the narrower, faster version.
Never use it on delimited data. On a fixed-column row it silently merges empty fields, so column 3 becomes column 2 and nothing errors — the bug shows up much later as a value in the wrong place. Use split(',') for anything with a delimiter, and this for anything a human typed as sentences.
The empty string, and a string of only whitespace, both yield no pieces — where split(' ') gives the empty string back as one piece, because n matches always yield n+1 and there is no special case for an empty haystack. Splitting on nothing follows that arithmetic to its end.
Example¶
str_split_whitespace.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let messy = " the quick \t brown \n fox ";
println!("{:?}", messy.split_whitespace().collect::<Vec<&str>>());
println!("{:?}", messy.split(' ').collect::<Vec<&str>>());
println!("{} vs {} pieces", messy.split_whitespace().count(), messy.split(' ').count());
// Trimming first is the half-fix: it takes the ends and leaves the runs.
println!("{:?}", messy.trim().split(' ').collect::<Vec<&str>>());
println!("{} pieces after trim, and the answer is still {}",
messy.trim().split(' ').count(), messy.split_whitespace().count());
// Never yields an empty piece.
println!("{:?}", " ".split_whitespace().collect::<Vec<&str>>());
println!("{:?}", "".split_whitespace().collect::<Vec<&str>>());
println!("{:?} <- the empty string is one piece to split, none to split_whitespace",
"".split(' ').collect::<Vec<&str>>());
// Unicode whitespace, not just the ASCII five.
println!("{:?}", "a\u{00A0}b".split_whitespace().collect::<Vec<&str>>());
// The trap: on delimited data it merges empty fields.
let row = "alice,,42";
let fields: Vec<&str> = row.split(',').collect();
println!("split(',') {:?} -> {} fields", fields, fields.len());
println!("whitespace route {:?} -> {} fields, and 42 is now column 2",
row.replace(',', " ").split_whitespace().collect::<Vec<&str>>(),
row.replace(',', " ").split_whitespace().count());
println!("{} words", "the quick brown fox".split_whitespace().count());
}
Verified output of str_split_whitespace.rs — regenerated by tools/run_examples.py, never hand-typed.
["the", "quick", "brown", "fox"]
["", "", "the", "", "", "quick", "\t", "brown", "\n", "fox", "", ""]
4 vs 12 pieces
["the", "", "", "quick", "\t", "brown", "\n", "fox"]
8 pieces after trim, and the answer is still 4
[]
[]
[""] <- the empty string is one piece to split, none to split_whitespace
["a", "b"]
split(',') ["alice", "", "42"] -> 3 fields
whitespace route ["alice", "42"] -> 2 fields, and 42 is now column 2
4 words
See also¶
str::split_ascii_whitespace— the ASCII-only, faster version- RFC 1054 — the method that renamed itself to promise less — why it is not called
words(), and why it is a method rather than a pattern str::split— the mechanical version, for delimited datastr::trim— the ends only, without splitting- Splitting on nothing — the same n+1 rule with an empty pattern, where it produces five pieces from three characters
str::lines— when the unit is a line rather than a word
str::split_whitespace in the standard library ↗
Po polsku¶
Ten podział jest redakcyjny, a nie mechaniczny: split_whitespace tnie po całych ciągach białych znaków i przycina końce, więc nigdy nie odda pustego kawałka — z " the quick \t brown \n fox " robi cztery słowa, podczas gdy split(' ') daje z tego samego tekstu dwanaście kawałków, w większości pustych. Białe znaki rozumiane są tu po unicodowemu (char::is_whitespace), a więc razem z tabulatorem, znakiem nowego wiersza i twardą spacją U+00A0, i to jest dokładnie ta metoda, którą chcesz mieć przy tekście napisanym albo wklejonym przez człowieka. Z tego samego powodu jest to wybór zły do danych z separatorem: w wierszu "alice,,42" pusta komórka zwyczajnie znika, 42 wskakuje do drugiej kolumny i nic nie zgłasza błędu — pomyłkę zobaczysz dopiero kilka warstw dalej, jako wartość w niewłaściwym polu. Podział ról jest więc sztywny: split(',') do danych, split_whitespace do prozy; pusty tekst i tekst złożony z samych spacji nie dają tutaj ani jednego kawałka.
Szukaj po polsku: dzielenie po białych znakach · liczenie słów w tekście · rust split_whitespace vs split · rust count words in string