Reputation: 34864
From the documentation, it's not clear. In Java you could use the split
method like so:
"some string 123 ffd".split("123");
Upvotes: 399
Views: 463848
Reputation: 9400
There is a special method split
for struct String
:
fn split<'a, P>(&'a self, pat: P) -> Split<'a, P> where P: Pattern<'a>
Split by word:
let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
Split by delimiter:
let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
assert_eq!(v, ["lion", "tiger", "leopard"]);
Split by closure:
let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
assert_eq!(v, ["abc", "def", "ghi"]);
Upvotes: 67
Reputation: 16188
Use split()
let parts = "some string 123 content".split("123");
This gives an iterator, which you can loop over, or collect()
into a vector. For example:
for part in parts {
println!("{}", part)
}
Or:
let collection = parts.collect::<Vec<&str>>();
dbg!(collection);
Or:
let collection: Vec<&str> = parts.collect();
dbg!(collection);
Upvotes: 463
Reputation: 713
If you are looking for the Python-flavoured split where you tuple-unpack the two ends of the split string, you can do
if let Some((a, b)) = line.split_once(' ') {
// ...
}
Upvotes: 16
Reputation: 3718
The OP's question was how to split with a multi-character string and here is a way to get the results of part1
and part2
as String
s instead in a vector
.
Here splitted with the non-ASCII character string "āāš¤"
in place of "123"
:
let s = "āāš¤"; // also works with non-ASCII characters
let mut part1 = "some string āāš¤ ffd".to_string();
let _t;
let part2;
if let Some(idx) = part1.find(s) {
part2 = part1.split_off(idx + s.len());
_t = part1.split_off(idx);
}
else {
part2 = "".to_string();
}
gets: part1 = "some string "
Ā Ā Ā Ā Ā part2 = " ffd"
If "āāš¤"
not is found part1
contains the untouched original String
and part2
is empty.
Here is a nice example in Rosetta Code -
Split a character string based on change of character - of how you can turn a short solution using split_off
:
fn main() {
let mut part1 = "gHHH5YY++///\\".to_string();
if let Some(mut last) = part1.chars().next() {
let mut pos = 0;
while let Some(c) = part1.chars().find(|&c| {if c != last {true} else {pos += c.len_utf8(); false}}) {
let part2 = part1.split_off(pos);
print!("{}, ", part1);
part1 = part2;
last = c;
pos = 0;
}
}
println!("{}", part1);
}
into that
Task
Split a (character) string into comma (plus a blank) delimited strings based on a change of character (left to right).
Upvotes: 3
Reputation: 15041
There are three simple ways:
By separator:
s.split("separator") | s.split('/') | s.split(char::is_numeric)
By whitespace:
s.split_whitespace()
By newlines:
s.lines()
By regex: (using regex
crate)
Regex::new(r"\s").unwrap().split("one two three")
The result of each kind is an iterator:
let text = "foo\r\nbar\n\nbaz\n";
let mut lines = text.lines();
assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());
assert_eq!(None, lines.next());
Upvotes: 222
Reputation: 23246
split
returns an Iterator
, which you can convert into a Vec
using collect
: split_line.collect::<Vec<_>>()
. Going through an iterator instead of returning a Vec
directly has several advantages:
split
is lazy. This means that it won't really split the line until you need it. That way it won't waste time splitting the whole string if you only need the first few values: split_line.take(2).collect::<Vec<_>>()
, or even if you need only the first value that can be converted to an integer: split_line.filter_map(|x| x.parse::<i32>().ok()).next()
. This last example won't waste time attempting to process the "23.0" but will stop processing immediately once it finds the "1".split
makes no assumption on the way you want to store the result. You can use a Vec
, but you can also use anything that implements FromIterator<&str>
, for example a LinkedList
or a VecDeque
, or any custom type that implements FromIterator<&str>
.Upvotes: 42
Reputation: 7657
There's also split_whitespace()
fn main() {
let words: Vec<&str> = " foo bar\t\nbaz ".split_whitespace().collect();
println!("{:?}", words);
// ["foo", "bar", "baz"]
}
Upvotes: 15