From the documentation, it's not clear. In Java you could use the split
method like so:
"some string 123 ffd".split("123");
Split
and set it into the array. Of course this means the number of items in each split must be the same since arrays are fixed size and you have to have the array defined before. I imagine this may be more trouble than simply creating a Vec
.
Use split()
let mut split = "some string 123 ffd".split("123");
This gives an iterator, which you can loop over, or collect()
into a vector.
for s in split {
println!("{}", s)
}
let vec = split.collect::<Vec<&str>>();
// OR
let vec: Vec<&str> = split.collect();
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());
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 char:
let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
Split by string:
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"]);
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::
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>.
let x = line.unwrap().split(",").collect::<Vec<_>>();
does not work unless it is separated into two separate lines: let x = line.unwrap();
and let x = x.split(",").collect::<Vec<_>>();
? The error message says: temporary value created here ^ temporary value dropped here while still borrowed
let x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();
There's also split_whitespace()
fn main() {
let words: Vec<&str> = " foo bar\t\nbaz ".split_whitespace().collect();
println!("{:?}", words);
// ["foo", "bar", "baz"]
}
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).
Success story sharing
.collect::<Vec<_>>()
.let split
?split.len()
doesn't exist..count()
.len()
is only for iterators which know their exact size without needing to be consumed,count()
consumes the iterator.error: cannot borrow immutable local variable
split` as mutable`let mut split
, sorry.