我已经在 Stackoverflow 中浏览了一些关于这个主题的帖子。我正在确认我是否得到了本质,正确的。
我想使用 Iterator 找出 Vector 中的最大值。由于这种方式,迭代器是在 Rust 中实现的(讨论here和here),我知道我将始终收到对元素(如果它存在)的引用而不是它的值。
这不编译。
pub struct WorkCard {
pub worker_id: u32,
pub largest_sack_moved_by_worker: u128,
pub sacks_moved: Vec<u128> // collection of duration of each call to API
}
impl WorkCard {
pub fn new(worker_id: u32, sacks_moved: Vec<u128>) -> WorkCard {
let mx = sacks_moved.iter().max().unwrap_or(0);
WorkCard { worker_id, largest_sack_moved_by_worker: mx, sacks_moved }
}
}
fn main() {
let sacks: Vec<u128> = vec![5,2,9,8,1];
let _worker1 = WorkCard::new(1 /* worker_id */, sacks /* sacks_moved */);
println("Worker {}, moved even a sack of {} KG!",
_worker1.worker_id,
_worker1.largest_sack_moved_by_worker
);
}
编译器清楚地指出了问题所在:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:9:53
|
9 | let mx = sacks_moved.iter().max().unwrap_or(0);
| --------- ^
| | |
| | expected `&u128`, found integer
| | help: consider borrowing here: `&0`
| arguments to this method are incorrect
|
help: the return type of this call is `{integer}` due to the type of the argument passed
--> src/main.rs:9:18
|
9 | let mx = sacks_moved.iter().max().unwrap_or(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
| |
| this argument influences the return type of `unwrap_or`
当然可以!
impl WorkCard {
pub fn new(worker_id: u32, sacks_moved: Vec<u128>) -> WorkCard {
let mx = sacks_moved.iter().max().unwrap_or(&(0 as u128)); // <-- forcing a numeric constant's reference
WorkCard { worker_id, largest_sack_moved_by_worker: *mx, sacks_moved } // <-- then, dereferencing !
}
}
我的问题是我是否应该认为这是一种从迭代器中获取最大(或最小)值的惯用方法。如果有更愉快的方式,我想学习。
因为顺便说一下,迭代器是在 Rust 中实现的(在这里和这里讨论过),我明白我将始终收到对元素(如果存在)的引用而不是它的值。
这不完全正确,您收到引用不是因为“迭代器在 Rust 中实现”的方式,而是因为您正在使用 借用迭代器(
slice::Iter
,由 slice::iter
返回) .
当然可以!
我不清楚你为什么要用
(0 as u128)
,&0
会很好用。即使没有,0u128
也会提供一个具体类型的常量。
我的问题是我是否应该认为这是一种从迭代器中获取最大(或最小)值的惯用方法。如果有更愉快的方式,我想学习。
旁观者眼中的愉悦,默认引用对我来说很好,但如上所述,您可以使用适配器将引用转换为拥有的值,
Iterator::copied
:
let mx = sacks_moved.iter().copied().max().unwrap_or(0);
Option::copied
:
let mx = sacks_moved.iter().max().copied().unwrap_or(0);