Equivalent to Python's str.partition()
method in Rust
So, Python's str.partition(sep)
is a minor convenience wrapper around .splitn(sep, 1)
.
Mainly, one could polyfill it as:
def partition(s: str, sep: str):
if not sep:
raise ValueError("Empty separator")
(before, *mb_after) = s.splitn(sep, 1)
return (before, *((sep, mb_after[0]) if mb_after else ("", "")))
Note how the core logic is still .split()
: str.partition()
tries to find a point in the string at which to split / cut the string in two parts.
In Rust, however, Iterator::partition
does not do that. Instead, given a predicate, it shall dispatch each element of the iterator to either of the two collections / "buckets" it returns: the left "bucket" will contain the elements that matched (so just '#'
s in your case), and the right bucket will contain the others).
So, if you want to implement .partition()
in Rust, just rewrite the Python function above in Rust
fn partition<'s, 'sep> (s: &'s str, sep: &'sep str)
-> (&'s str, &'sep str, &'s str)
{
if sep.is_empty() {
panic!("Empty separator");
}
let mut iter = s.splitn(sep, 1);
let before = iter.next().unwrap();
if let after = iter.next() {
(before, sep, after)
} else {
(before, "", "")
}
}
Although using "sentinel values (such as ""
) to signal an error / special case is not very idiomatic in Rust, where we have the wonderful Option
enum
:
fn partition<'s, 'sep> (s: &'s str, sep: &'sep str)
-> (&'s str, Option<&'s str>)
{
if sep.is_empty() {
panic!("Empty separator");
}
let mut iter = s.splitn(sep, 1);
(
iter.next().unwrap(),
iter.next(),
)
}
EDIT: at that point we are very close to the signature of @steffahn's very aptly suggested .split_once()
function