Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Rust中实现多值迭代器模式?_Rust - Fatal编程技术网

如何在Rust中实现多值迭代器模式?

如何在Rust中实现多值迭代器模式?,rust,Rust,我有一个迭代器类型的对象,每次调用它时可以返回零个、一个或多个项。我想实现一个标准的IterAPI,即next返回选项,这样就可以逐项消费 在Clojure中,我可能会使用mapcat(“映射并连接”)来实现这一点 我当前的解决方案(感谢@Ryan)使用了平面地图,但仍然需要大量的分配: // Desired input: // A stateful object that implements an iterator which returns a number of results each

我有一个迭代器类型的对象,每次调用它时可以返回零个、一个或多个项。我想实现一个标准的
Iter
API,即
next
返回
选项
,这样就可以逐项消费

在Clojure中,我可能会使用
mapcat
(“映射并连接”)来实现这一点

我当前的解决方案(感谢@Ryan)使用了
平面地图
,但仍然需要大量的分配:

// Desired input:
// A stateful object that implements an iterator which returns a number of results each time.
// The real code is a bit more complicated, this is the minimal example.
struct MyThing {
    counter: i32,
}

impl Iterator for MyThing {
    type Item = Vec<String>;

    fn next(&mut self) -> Option<Vec<String>> {
        self.counter += 1;
        if self.counter == 4 {
            self.counter = 1;
        }

        match self.counter {
            1 => Some(vec!["One".to_string()]),
            2 => Some(vec!["One".to_string(), "Two".to_string()]),
            3 => Some(vec![
                "One".to_string(),
                "Two".to_string(),
                "Three".to_string(),
            ]),
            _ => Some(vec![]),
        }
    }
}

fn main() {
    let things = MyThing { counter: 0 };

    // Missing piece, though the following line does the job:
    let flattened = things.flat_map(|x| x);

    // However this requires a heap allocation at each loop.

    // Desired output: I can iterate, item by item.
    for item in flattened {
        println!("{:?}", item);
    }
}
//所需输入:
//一个有状态的对象,它实现了一个迭代器,每次都返回许多结果。
//真正的代码有点复杂,这是最简单的例子。
结构神话{
柜台:i32,
}
impl神话迭代器{
项目类型=Vec;
fn下一步(&mut self)->选项{
自计数器+=1;
如果self.counter==4{
self.counter=1;
}
匹配自动计数器{
1=>Some(vec![“One.”to_string()),
2=>Some(vec![“一.到字符串(),“两.到字符串()]),
3=>一些(vec[
“一”。到字符串(),
“两个”。to_string(),
“三个”。to_string(),
]),
_=>一些(vec![]),
}
}
}
fn main(){
让事物=虚构{计数器:0};
//缺少一块,尽管以下行可以完成此工作:
让展平=事物。展平映射(| x | x);
//但是,这需要在每个循环中分配堆。
//所需输出:我可以逐项迭代。
对于展平的项目{
println!(“{:?}”,项目);
}
}

鉴于我所看到的创新之处,我想知道是否有一种更惯用、成本更低的方法来实现此模式。

如果您知道如何以编程方式生成“内部”值,请将
Vec
替换为您定义的实现
迭代器的结构。(从技术上讲,只需要
迭代器
,但
迭代器
就足够了。)

如您所知,会展平嵌套结构,因此如下所示:

在实际代码中,
内部
外部
在大多数情况下可能与此示例非常不同。例如,如果不执行与分配
Vec
等效的操作,就不一定能够编写
内部
。因此,这些迭代器的精确形状和语义取决于关于用例的具体信息


以上假设
internal
在某种程度上是有用的,或者更容易单独实现。您可以很容易地编写一个在序列上迭代的结构,而无需展平,但是您还必须将内部迭代器状态(索引
字段)放入外部
中:

struct Outer {
    index: usize,
    counter: i32,
}

impl Iterator for Outer {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        static WORDS: [&str; 3] = ["One", "Two", "Three"];
        let result = WORDS.get(self.index).map(|r| r.to_string());
        self.index += 1;
        if self.index >= self.counter as usize {
            self.counter = 1 + self.counter % 3;
            self.index = 0;
        };
        result
    }
}

fn main() {
    let things = Outer { counter: 1, index: 0 };

    for item in things.take(100) {
        println!("{:?}", item);
    }
}
struct-Outer{
索引:usize,
柜台:i32,
}
外部函数的impl迭代器{
类型项=字符串;
fn下一步(&mut self)->选项{
静态词:[&str;3]=[“一”、“二”、“三”];
让result=WORDS.get(self.index).map(|r | r.to_string());
自指数+=1;
如果self.index>=使用self.counter{
self.counter=1+self.counter%3;
self.index=0;
};
结果
}
}
fn main(){
让things=Outer{counter:1,index:0};
对于物品中的物品。取(100){
println!(“{:?}”,项目);
}
}

你能进一步解释一下你的问题吗:(a)你的“迭代器类型对象”到底返回了什么,(b)为什么
iterator::flat_map
是不够的,(c)你所说的“小缓冲迭代器”是什么意思?你的问题说你想“实现一个多值迭代器”,但这对我来说没有任何意义。您声明您已经有了一个“迭代器类型对象”,那么为什么要询问如何实现它呢?示例分配是因为迭代器本身进行分配。如果您有一个不分配的迭代器,对其调用
.flat\u map()
不会导致它分配。在您的实际实现中,这些项来自哪里?您可以通过维护第二个计数器来跟踪哪个数字来避免
Vec
s,但如果很难说什么适用于您的真实代码,则没有一个代表性的示例。
struct Outer {
    counter: i32,
}

impl Iterator for Outer {
    type Item = Inner;

    fn next(&mut self) -> Option<Inner> {
        self.counter = 1 + self.counter % 3;

        Some(Inner::new(self.counter as usize))
    }
}
let things = Outer { counter: 0 };

for item in things.flat_map(|x| x).take(100) {
    println!("{:?}", item);
}
struct Outer {
    index: usize,
    counter: i32,
}

impl Iterator for Outer {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        static WORDS: [&str; 3] = ["One", "Two", "Three"];
        let result = WORDS.get(self.index).map(|r| r.to_string());
        self.index += 1;
        if self.index >= self.counter as usize {
            self.counter = 1 + self.counter % 3;
            self.index = 0;
        };
        result
    }
}

fn main() {
    let things = Outer { counter: 1, index: 0 };

    for item in things.take(100) {
        println!("{:?}", item);
    }
}