15

I want to split a string by a separator only once and put it into a tuple. I tried doing

fn splitOnce(in_string: &str) -> (&str, &str) {
    let mut splitter = in_string.split(':');
    let first = splitter.next().unwrap();
    let second = splitter.fold("".to_string(), |a, b| a + b); 
    (first, &second)
}

but I keep getting told that second does not live long enough. I guess it's saying that because splitter only exists inside the function block but I'm not really sure how to address that. How to I coerce second into existing beyond the function block? Or is there a better way to split a string only once?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
erp
  • 515
  • 1
  • 5
  • 14

2 Answers2

22

You are looking for str::splitn:

fn split_once(in_string: &str) -> (&str, &str) {
    let mut splitter = in_string.splitn(2, ':');
    let first = splitter.next().unwrap();
    let second = splitter.next().unwrap();
    (first, second)
}

fn main() {
    let (a, b) = split_once("hello:world:earth");
    println!("{} --- {}", a, b)
}

Note that Rust uses snake_case.


I guess it's saying that because splitter only exists inside the function block

Nope, it's because you've created a String and are trying to return a reference to it; you cannot do that. second is what doesn't live long enough.

How to I coerce second into existing beyond the function block?

You don't. This is a fundamental aspect of Rust. If something needs to live for a certain mount of time, you just have to make it exist for that long. In this case, as in the linked question, you'd return the String:

fn split_once(in_string: &str) -> (&str, String) {
    let mut splitter = in_string.split(':');
    let first = splitter.next().unwrap();
    let second = splitter.fold("".to_string(), |a, b| a + b); 
    (first, second)
}
Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
9

str::split_once is now built-in.

Doc examples:

assert_eq!("cfg".split_once('='), None);
assert_eq!("cfg=".split_once('='), Some(("cfg", "")));
assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo")));
assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar")));
Carl Walsh
  • 6,100
  • 2
  • 46
  • 50