I'd like to efficiently, preferably in a functional way, truncate an existing BTreeMap from a reference and return a cloned, truncated BTreeMap of the same key-value pairs.
use std::collections::BTreeMap;
/// I want to return a BTreeMap containing only the first 2 keys.
fn truncate(b: &BTreeMap<u32, u32>) -> BTreeMap<u32, u32> {
b.iter().take(2).cloned().collect()
}
fn main() {
let mut b = BTreeMap::new();
b.insert(1, 1);
b.insert(2, 1);
b.insert(3, 1);
let t = truncate(&b);
}
The error message:
expected an iterator that yields
&_
, but it yields(&u32, &u32)
It might be useful to consider all error messages (Playground):
error[E0271]: expected `std::iter::Take<std::collections::btree_map::Iter<'_, u32, u32>>` to be an iterator that yields `&_`, but it yields `(&u32, &u32)`
--> src/main.rs:5:5
|
5 | b.iter().take(2).cloned().collect()
| ^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
| |
| expected reference, found tuple
|
= note: expected reference `&_`
found tuple `(&u32, &u32)`
note: required by a bound in `cloned`
--> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/iter/traits/iterator.rs:3271:32
|
= note: required by this bound in `cloned`
.cloned()
will turn an iterator over &T
into an iterator over T
. But you have an iterator over (&u32, &u32)
, which .cloned()
simply can't be used on. Even if you had &(&u32, &u32)
, you'd only get (&u32, &u32)
.
In this case, there is no neat function that you could use to take care of stripping the references, you'll need to write it yourself.
b.iter().take(2).map(|(&a, &b)| (a, b)).collect()