基本上,我有一个函数来过滤所有长度最长的字符串。为了避免错误expected struct 'String', found '&String',我尝试了以下两种解决方案。他们都给出了正确的结果。
用into_iter
fn allLongestStrings(inputArray: Vec<String>) -> Vec<String> {
let max_len = inputArray.iter().map(|string| string.len()).max().unwrap();
inputArray.into_iter().filter(|string| string.len().eq(&max_len)).collect()
}用iter
fn allLongestStrings(inputArray: Vec<String>) -> Vec<String> {
let max_len = inputArray.iter().map(|string| string.len()).max().unwrap();
inputArray.iter().filter(|string| string.len().eq(&max_len)).map(|s| s.to_string()).collect()
}into_iter看起来更干净,但是在这个回答中,它说into_iter的结果有时令人惊讶。
发布于 2021-09-23 21:32:19
假设这两种方法都以值表示向量,那么第一个版本(使用into_iter())会更好,因为它不会复制字符串。
当一个字符串与条件匹配时,它将被移动到目标向量中。使用第二个版本(使用iter())时,当字符串与谓词匹配时,将复制该字符串,并将副本移动到目标vector.This中,从而产生更多的分配和更多的释放。
下面是简单的标准基准测试,以证明:
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; //0.3.5
criterion_group!(benches, benchmark);
criterion_main!(benches);
pub fn benchmark(c: &mut Criterion) {
let input = vec![
"some string".to_owned(),
"some string".to_owned(),
"some string".to_owned(),
"some string".to_owned(),
"some string".to_owned(),
"some string".to_owned(),
"some string".to_owned(),
];
c.bench_with_input(BenchmarkId::new("with_iter", ""), &input, |b, i| {
b.iter(|| {
let result = with_iter(i.clone());
black_box(result);
});
});
c.bench_with_input(BenchmarkId::new("with_into_iter", ""), &input, |b, i| {
b.iter(|| {
let result = with_into_iter(i.clone());
black_box(result);
});
});
}
fn with_into_iter(input_array: Vec<String>) -> Vec<String> {
let max_len = input_array.iter().map(|string| string.len()).max().unwrap();
input_array
.into_iter()
.filter(|string| string.len() == max_len)
.collect()
}
fn with_iter(input_array: Vec<String>) -> Vec<String> {
let max_len = input_array.iter().map(|string| string.len()).max().unwrap();
input_array
.iter()
.filter(|string| string.len() == max_len)
.map(|s| s.to_string())
.collect()
}这显然是复制所有值的极端情况。根据您的输入,如果要复制的短字符串很少,则差异可能可以忽略不计。
with_iter/ time: [392.30 ns 394.80 ns 397.93 ns]
with_into_iter/ time: [153.07 ns 153.41 ns 153.79 ns] 显然,时间取决于要复制的字符串的数量及其长度,因此实际的时间取决于函数的输入。
PS:如果你想尽可能快,你可以使用retain()
fn with_retain(mut input_array: Vec<String>) -> Vec<String> {
let max_len = input_array.iter().map(|string| string.len()).max().unwrap();
input_array.retain(|string| string.len() == max_len);
input_array
}with_retain/ time: [143.98 ns 144.22 ns 144.50 ns] 它更快,因为:
缺点是,如果长输入数组上的匹配非常少,那么输出向量就会太大,从而浪费一些内存。
https://stackoverflow.com/questions/69303336
复制相似问题