gpt4 book ai didi

iterator - 如何返回调用 filter_map 的结果

转载 作者:行者123 更新时间:2023-11-29 08:05:25 24 4
gpt4 key购买 nike

这里我有一个 (char, usize) 对的向量 vec,我想写一个函数

fn take_lt(&'a vec, cutoff: usize) -> Iterator<'a, char>

返回小于截止值的字符匹配值的迭代器。

  1. 有没有一种方法可以做到这一点而无需为堆分配一些东西(即装箱 Fn 环境或创建另一个向量)?
  2. 有没有办法做到这一点
    无需显式写出可怕的相关返回类型?

在尝试了很多不同的方法之后(其中一些已编译,但所有这些都涉及我想避免的堆分配),我想出了:

use std::iter::repeat;
use std::iter::FilterMap;
use std::iter::Zip;
use std::iter::Repeat;
use std::slice;

fn take_lt<'a>(vec: &'a[(char, usize)], cutoff: usize) -> FilterMap<Zip<slice::Iter<'a, (char, usize)>, Repeat<usize>>, &fn((&(char, usize), usize)) -> Option<char>> {
fn cmp_fun((&(x, a), b): (&(char, usize), usize)) -> Option<char> {
if a < b {
Some(x)
} else {
None
}
}
vec.iter().zip(repeat(cutoff)).filter_map(&cmp_fun)
}

这很接近,但我得到:

src/lib.rs:15:47: 15:55 error: mismatched types:
expected `&fn((&(char, usize), usize)) -> core::option::Option<char>`,
found `&fn((&(char, usize), usize)) -> core::option::Option<char> {take_lt::cmp_fun}`
(expected fn pointer,
found fn item) [E0308]
src/lib.rs:15 vec.iter().zip(repeat(cutoff)).filter_map(&cmp_fun)
^~~~~~~~

谷歌搜索建议我尝试将函数项转换为函数指针,如:

vec.iter().zip(repeat(cutoff)).filter_map(&(cmp_fun as fn((&(char, usize), usize)) -> Option<char>))

但是失败了:

src/lib.rs:15:49: 15:103 error: borrowed value does not live long enough
src/lib.rs:15 vec.iter().zip(repeat(cutoff)).filter_map(&(cmp_fun as fn((&(char, usize), usize)) -> Option<char>))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/lib.rs:7:167: 16:2 note: reference must be valid for the lifetime 'a as defined on the block at 7:166...
src/lib.rs: 7 fn take_lt<'a>(vec: &'a[(char, usize)], cutoff: usize) -> FilterMap<Zip<slice::Iter<'a, (char, usize)>, Repeat<usize>>, &fn((&(char, usize), usize)) -> Option<char>> {
src/lib.rs: 8 fn cmp_fun((&(x, a), b): (&(char, usize), usize)) -> Option<char> {
src/lib.rs: 9 if a < b {
src/lib.rs:10 Some(x)
src/lib.rs:11 } else {
src/lib.rs:12 None
...
src/lib.rs:7:167: 16:2 note: ...but borrowed value is only valid for the block at 7:166
src/lib.rs: 7 fn take_lt<'a>(vec: &'a[(char, usize)], cutoff: usize) -> FilterMap<Zip<slice::Iter<'a, (char, usize)>, Repeat<usize>>, &fn((&(char, usize), usize)) -> Option<char>> {
src/lib.rs: 8 fn cmp_fun((&(x, a), b): (&(char, usize), usize)) -> Option<char> {
src/lib.rs: 9 if a < b {
src/lib.rs:10 Some(x)
src/lib.rs:11 } else {
src/lib.rs:12 None
...

最佳答案

你很接近:

// type alias for the return type (optional, I just find it a bit
// optically easier to work with). I added:
// a 'a lifetime parameter that ties the return Iter lifetime to the
// input slice
// a 'static lifetime for the function pointer
type RetTake<'a> = FilterMap<Zip<slice::Iter<'a, (char, usize)>,
Repeat<usize>>, &'static fn((&(char, usize), usize)) -> Option<char>>;

fn take_lt<'a>(vec: &'a[(char, usize)], cutoff: usize) -> RetTake {
fn cmp_fun((&(x, a), b): (&(char, usize), usize)) -> Option<char> {
if a < b {
Some(x)
} else {
None
}
}

// I think this explicit static binding
// used not to be necessary, but I now can't get rustc
// to give the reference to the function pointer the static lifetime
// it needs otherwise
static F: fn((&(char, usize), usize)) -> Option<char> = cmp_fun;
vec.iter().zip(repeat(cutoff)).filter_map(&F)
}

作为替代方案,您可以创建自己的结构来实现所需的迭代器逻辑并返回该结构。例如:

struct CutoffIterator<'a> {
iter: slice::Iter<'a, (char, usize)>,
cutoff: usize,
}

impl<'a> Iterator for CutoffIterator<'a> {
type Item = char;

fn next(&mut self) -> Option<char> {
loop {
match self.iter.next() {
Some(&(x, a)) if a < self.cutoff => return Some(x),
Some(&(_, a)) if a >= self.cutoff => continue,
_ => return None
}
}
}
}

fn take_lt2(vec: &[(char, usize)], cutoff: usize) -> CutoffIterator {
CutoffIterator { iter: vec.iter(), cutoff: cutoff }
}

关于iterator - 如何返回调用 filter_map 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34459976/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com