string - 如何生成随机的字母数字字符串?
问题描述
问题的第一部分可能很常见,并且有足够的代码示例来解释如何生成随机的字母数字字符串。我使用的代码来自这里。
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
fn main() {
let rand_string: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.collect();
println!("{}", rand_string);
}
然而,这段代码没有编译,(注意:我每晚都在):
error[E0277]: a value of type `String` cannot be built from an iterator over elements of type `u8`
--> src/main.rs:8:10
|
8 | .collect();
| ^^^^^^^ value of type `String` cannot be built from `std::iter::Iterator<Item=u8>`
|
= help: the trait `FromIterator<u8>` is not implemented for `String`
好的,生成的元素是 type u8
。所以我猜这是一个数组或向量u8
:
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
fn main() {
let r = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.collect::<Vec<_>>();
let s = String::from_utf8_lossy(&r);
println!("{}", s);
}
这可以编译和工作!
2dCsTqoNUR1f0EzRV60IiuHlaM4TfK
一切都很好,除了我想问一下是否有人可以解释关于类型的确切情况以及如何优化它。
问题
.sample_iter(&Alphanumeric)
产生u8
而不是char
s?- 如何避免第二个变量
s
并直接将 an 解释u8
为 utf-8 字符?我猜内存中的表示根本不会改变? - 这些字符串的长度应始终为 30。如何优化 a
Vec
away 的堆分配?它们实际上也可以char[]
代替String
s。
解决方案
.sample_iter(&Alphanumeric)
产生 u8 而不是字符?
是的,这在 rand v0.8 中已更改。您可以在 0.7.3 的文档中看到:
impl Distribution<char> for Alphanumeric
impl Distribution<u8> for Alphanumeric
如何避免第二个变量
s
并直接将 an 解释u8
为 utf-8 字符?我猜内存中的表示根本不会改变?
有几种方法可以做到这一点,最明显的是将 everyu8
转换为 a char
:
let s: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.map(|x| x as char)
.collect();
或者,使用以下From<u8>
实例char
:
let s: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.map(char::from)
.collect();
当然在这里,既然你知道每个都u8
必须是有效的 UTF-8,你可以使用String::from_utf8_unchecked
,它比from_utf8_lossy
(尽管可能与as char
方法的速度差不多)更快:
let s = unsafe {
String::from_utf8_unchecked(
thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.collect::<Vec<_>>(),
)
};
如果由于某种原因unsafe
困扰你并且你想保持安全,那么你可以使用较慢的String::from_utf8
,所以你会得到一个恐慌而不是 UB(即使代码永远不应该恐慌或 UB):unwrap
Result
let s = String::from_utf8(
thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.collect::<Vec<_>>(),
).unwrap();
这些字符串的长度应始终为 30。如何优化 a
Vec
away 的堆分配?它们实际上也可以char[]
代替字符串。
首先,相信我,你不想要字符数组。与他们一起工作并不有趣。如果您想要一个堆栈字符串,请有一个u8
数组,然后使用类似std::str::from_utf8
或更快的函数std::str::from_utf8_unchecked
(再次仅可用,因为您知道将生成有效的 utf8。)
至于优化堆分配,请参阅this answer。基本上,有一点hackiness/ugliness是不可能的(比如制作你自己的函数,将迭代器收集到一个30个元素的数组中)。
一旦const 泛型最终稳定下来,就会有一个更漂亮的解决方案。
推荐阅读
- ruby-on-rails - 如何获取 f.select 的静态哈希值导轨?
- vb.net - 我无法将粗体格式粘贴到 VB.NET Winforms 中的 RichTextBox
- c# - 渲染设计师创建的卡片时出现异常
- sql-server - 恢复数据库保留视图
- javascript - dict 对象形成数据以在 VueJS 中进行补丁操作
- terraform - 如何在 terraform 中用本地后端覆盖远程后端?
- linq - 动态 Linq 核心
- c++ - 为什么第一个代码块产生垃圾值,而第二个代码块将类成员的值相加?
- java - 将枚举值与类字段匹配
- javascript - MongoDB 数据库服务未启动