从字符串中获取一个随机字符并附加到另一个字符串 [英] Get a random character from a string and append to another string

查看:37
本文介绍了从字符串中获取一个随机字符并附加到另一个字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写与以下 C++ 代码等效的 Rust:

I'm trying to write the Rust equivalent of the following C++ code:

result += consonants[rand() % consonants.length()];

它的目的是从字符串 consonants 中取出一个随机字符并将其附加到字符串 result 中.

It is meant to take a random character from the string consonants and append it to the string result.

我似乎找到了一个可以工作的 Rust 等价物,但至少可以说它......太可怕了.什么是更惯用的等价物?

I seem to have found a working Rust equivalent, but it's... monstrous, to say the least. What would be a more idiomatic equivalent?

format!("{}{}", result, consonants.chars().nth(rand::thread_rng().gen_range(1, consonants.chars().count())).unwrap().to_string());

推荐答案

一些事情:

  • 您不需要在此处使用 format!().有 String::push() 附加单个字符.

  • You don't need to use format!() here. There is String::push() which appends a single char.

还有 rand::sample() 函数可以从迭代器中随机选择多个元素.这看起来很合适!

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 --+

(游乐场)

我们只从迭代器中采样一个元素,并立即将其推送到字符串中.仍然不如 C 的 rand() 短,但请注意 rand() 被认为是有害的 任何类型的严重使用!使用 C++ 的 标头要好得多,但也需要更多的代码.此外,您的 C 版本无法处理多字节字符(例如 UTF-8 编码),而 Rust 版本具有完整的 UTF-8 支持.

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.

然而,如果你只想有一个带有英文辅音的字符串,那么就不需要 UTF-8,我们可以使用 O(1) 索引,通过使用字节切片:

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` ^^^^

(游乐场)

正如评论中提到的,您可能只想要一组字符(辅音").这意味着,我们不必使用字符串,而是使用 chars 数组.所以这是最后一个支持 UTF-8 的版本并且避免了 O(n) 索引:

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());

(游乐场)

这篇关于从字符串中获取一个随机字符并附加到另一个字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆