微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

除了 Rust 迭代器中的最后一项之外,如何重复克隆操作?

如何解决除了 Rust 迭代器中的最后一项之外,如何重复克隆操作?

我经常看到我需要遍历一个范围并调用一个拥有其参数所有权的函数的模式。由于该函数拥有其参数的所有权,因此我必须克隆该值。例如:

let a = "hello".to_string();
for i in 0..10 {
    print_me(a.clone());
}

fn print_me(s: String) {
    println!("{}",s);
}

我想找到一种模式,为所有调用复制值除了最后一个,以防止重复复制。

最简单的方法是对循环索引添加显式检查:

for i in 0..10 {
    if i == 9 {
        print_me(a);
    } else {
        print_me(a.clone());
    }
}

但编译器无法理解该模式并在迭代期间抱怨移动的值。

我还尝试构建一个迭代器,使用 repeat_with()chain()once() 执行克隆和移动,但闭包使用了该值:

let iter = std::iter::repeat_with(|| a.clone())
            .take(9)
            .chain(std::iter::once(a))

实现这种模式的最简单方法是什么?

谢谢!

解决方法

作为替代解决方案,您可以通过跳出循环让编译器了解它实际上是最后一次迭代:

for i in 0..10 {
    if i == 9 {
        print_me(a);
        break;
    } else {
        print_me(a.clone());
    }
}
,

itertools::repeat_n 正是这样做的:

#[derive(Clone,Debug)]
pub struct RepeatN<A> {
    elt: Option<A>,n: usize,}

/// Create an iterator that produces `n` repetitions of `element`.
pub fn repeat_n<A: Clone>(element: A,n: usize) -> RepeatN<A> {
    if n == 0 {
        RepeatN { elt: None,n,}
    } else {
        RepeatN { elt: Some(element),}
    }
}

impl<A: Clone> Iterator for RepeatN<A> {
    type Item = A;

    fn next(&mut self) -> Option<Self::Item> {
        if self.n > 1 {
            self.n -= 1;
            self.elt.as_ref().cloned()
        } else {
            self.n = 0;
            self.elt.take()
        }
    }

    fn size_hint(&self) -> (usize,Option<usize>) {
        (self.n,Some(self.n))
    }
}

使用 unsafe 代码可以使实现(稍微)更有效。

,

一个简单的解决方案,但可能不是最快的
至少它避免了对最后一项的检查

if let Some((last,lead)) = (0..10).collect::<Vec<u16>>().split_last() {
    for _ in lead {
        print_me(a.clone());
    }
    print_me(a);  // last
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。