I\'m trying to write the Rust equivalent of the following C++ code:
result += consonants[rand() % consonants.length()];
<
A few things:
You don't need to use format!()
here. There is String::push() which appends a single char.
There is also the rand::sample() function which can randomly choose multiple elements from an iterator. This looks like the perfect fit!
So let's see how this fits together! I created three different versions for different use cases.
let consonants = "bcdfghjklmnpqrstvwxyz";
let mut result = String::new();
result.push(rand::sample(&mut rand::thread_rng(), consonants.chars(), 1)[0]);
// | |
// sample one element from the iterator --+ |
// |
// get the first element from the returned vector --+
(Playground)
We sample only one element from the iterator and immediately push it to the string. Still not as short as with C's rand()
, but please note that rand() is considered harmful for any kind of serious use! Using C++'s <random>
header is a lot better, but will require a little bit more code, too. Additionally, your C version can't handle multi-byte characters (e.g. UTF-8 encoding), while the Rust version has full UTF-8 support.
However, if you only want to have a string with English consonants, then UTF-8 is not needed and we can make use of O(1) indexing, by using a byte slice:
use rand::{thread_rng, Rng};
let consonants = b"bcdfghjklmnpqrstvwxyz";
let mut result = String::new();
result.push(thread_rng().choose(consonants).cloned().unwrap().into());
// convert Option<&u8> into Option<u8> ^^^^^^
// unwrap, because we know `consonants` is not empty ^^^^^^
// convert `u8` into `char` ^^^^
(Playground)
As mentioned in the comments, you probably just want a collection of characters ("consonants"). This means, we don't have to use a string, but rather an array of chars
. So here is one last version which does have UTF-8 support and avoids O(n) indexing:
use rand::{thread_rng, Rng};
// If you need to avoid the heap allocation here, you can create a static
// array like this: let consonants = ['b', 'c', 'd', ...];
let consonants: Vec<_> = "bcdfghjklmnpqrstvwxyz".chars().collect();
let mut result = String::new();
result.push(*thread_rng().choose(&consonants).unwrap());
(Playground)