David Stalnaker
David Stalnaker

Reputation: 223

How to partition a string at a fixed index?

I have a String (in particular a SHA1 hex digest) that I would like to split into two substrings - the first two characters and the rest of of the string. Is there a clean way to do this in Rust?

Upvotes: 7

Views: 9363

Answers (4)

robinst
robinst

Reputation: 31407

There's a split_at method since Rust 1.4, use it like this:

let s = "13e3f28a65a42bf6258cbd1d883d1ce3dac8f085";
let (first, last) = s.split_at(2);

assert_eq!("13", first);
assert_eq!("e3f28a65a42bf6258cbd1d883d1ce3dac8f085", last);

Note that the index is a byte position and must lie on a character boundary. In this case this works because you know that your input string is ASCII.

Upvotes: 15

bluss
bluss

Reputation: 13772

Here is a way to efficiently split a String into two Strings, in case you have this owned string data case. The allocation of the input string is retained in the first piece by just using truncation.

/// Split a **String** at a particular index
///
/// **Panic** if **byte_index** is not a character boundary
fn split_string(mut s: String, byte_index: usize) -> (String, String)
{
    let tail = s[byte_index..].into();
    s.truncate(byte_index);
    (s, tail)
}

Note: The .into() method is from the generic conversion trait Into and in this case it converts &str into String.

Upvotes: 1

oli_obk
oli_obk

Reputation: 31173

If you are expecting two Strings instead of slices, you can use the chars() method and some Iterator methods to obtain them.

let text = "abcdefg".to_string();
let start: String = text.chars().take(2).collect();
let end: String = text.chars().skip(2).collect();

If you don't want to do heap allocations, you can use slices instead:

let start: &str = text.slice_chars(0, 2);
let end: &str = text.slice_chars(2, text.char_len());

Note that the slices version requires you to use unstable rust (nightly builds, not the beta)

Upvotes: 5

Vladimir Matveev
Vladimir Matveev

Reputation: 127761

If you know that your string only contains ASCII characters (as in case with sha digests), you can use slices directly:

let s = "13e3f28a65a42bf6258cbd1d883d1ce3dac8f085";
let first = &s[..2];  // "13"
let rest = &s[2..];   // "e3f28a65a42bf6258cbd1d883d1ce3dac8f085"

It won't work correctly if your string contains non-ASCII characters because slicing uses byte offsets, and if any index used in slicing points into the middle of a code point representation, your program will panic.

Upvotes: 13

Related Questions