I'm trying to reverse a string. I use the solution of this post and it works.
But I would like to try with bytes instead of grapheme clusters as shown below:
pub fn reverse2(input: &str) -> String {
let s: String = input
.as_bytes()
.iter()
.rev()
.collect();
return s;
}
Unfortunately, I can't run the function collect()
after rev()
. I don't know which method to use. How would you do it ?
CodePudding user response:
As you explicitly ask about not using chars()
, you have to restrict yourself to ASCII strings.
pub fn reverse2(input: &str) -> String {
// Reversing on byte-level only works with ASCII strings.
assert!(input.is_ascii());
let reversed_bytes: Vec<u8> = input.as_bytes().iter().copied().rev().collect();
let reversed_string = unsafe {
// SAFETY: This is guaranteed to be a valid UTF8 string, because:
// - the input string is a valid ASCII string
// - a reversed ASCII string is still a valid ASCII string
// - an ASCII string is a valid UTF8 string
String::from_utf8_unchecked(reversed_bytes)
};
return reversed_string;
}
You can also use the checked version, if you don't like the unsafe
, but it comes with a little bit of overhead:
pub fn reverse2(input: &str) -> String {
// Reversing on byte-level only works with ASCII strings.
assert!(input.is_ascii());
let reversed_bytes: Vec<u8> = input.as_bytes().iter().copied().rev().collect();
let reversed_string = String::from_utf8(reversed_bytes).unwrap();
return reversed_string;
}
Optimization:
Checking is_ascii()
is some overhead. It is not strictly required, however.
UTF-8 has one special property: every non-ASCII byte is valued 128
and above. So technically it is enough to just simply filter out all values equal to or above 128
:
pub fn reverse2(input: &str) -> String {
let reversed_bytes: Vec<u8> = input
.as_bytes()
.iter()
.rev()
.map(|&val| {
if val < 128 {
val
} else {
0x1a // replacement char
}
})
.collect();
let reversed_string = unsafe {
// SAFETY: This is guaranteed to be a valid UTF8 string, because:
// - `reversed_bytes` is guaranteed to be an ASCII string
// - an ASCII string is a valid UTF8 string
String::from_utf8_unchecked(reversed_bytes)
};
return reversed_string;
}
fn main() {
let s = "abcde