当前位置: 首页 > 知识库问答 >
问题:

交替迭代

蓝恩
2023-03-14

我试图迭代一个分成块的切片,并返回一个元组,其中包含每个块的第n个元素。

示例:

我想将其分成大小为3的块,然后迭代结果,返回这些元组,每次调用next()时返回一个元组:

我知道,对于一般的东西,不可能返回可变的东西,mut这显然是不相交的,没有不安全的代码,我们就可以得到ChunksMut(https://doc.rust-lang.org/std/slice/struct.ChunksMut.html)迭代器,所以也许有办法!。例如,我可以有3个ChunksMut,然后编译器知道从它们返回的元素是不相交的。

这是我对不可变的尝试:

https://play.rust-lang.org/?version=stable

PS:我想避免每次迭代中的Vec或任何分配


共有2个答案

亢琦
2023-03-14

我很确定您想使用迭代器将可变引用引入原始切片,从而导致

没有分配/不安全/外部板条箱。需要生锈版本1.55或更高版本:

fn iter_chunks<T, const CHUNK_SIZE: usize>(
    slice: &mut [T],
) -> impl Iterator<Item = [&mut T; CHUNK_SIZE]> + '_ {
    assert_eq!(slice.len() % CHUNK_SIZE, 0);
    let len = slice.len();
    let mut a: [_; CHUNK_SIZE] = array_collect(
        slice
            .chunks_mut(len / CHUNK_SIZE)
            .map(|iter| iter.iter_mut()),
    );
    (0..len / CHUNK_SIZE).map(move |_| array_collect(a.iter_mut().map(|i| i.next().unwrap())))
}

/// Builds an array from the first `N` items of an iterator
///
/// Panics:
///
/// If there are less then `N` items in the iterator
fn array_collect<T, const N: usize>(mut iter: impl Iterator<Item = T>) -> [T; N] {
    let a: [(); N] = [(); N];
    a.map(|_| iter.next().unwrap())
}

无需分配,使用外部板条箱:

我们需要使用arrayvec,因为Rust的数组不能与收集一起使用。

use arrayvec::ArrayVec;

fn main() {
    let slice = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9];
    for (i, chunk) in iter_chunks::<_, 3>(slice).enumerate() {
        println!("{:?}", chunk);
        for t in chunk {
            *t = i;
        }
    }
    println!("slice: {:?}", slice);
}

fn iter_chunks<T, const CHUNK_SIZE: usize>(
    slice: &mut [T],
) -> impl Iterator<Item = ArrayVec<&mut T, CHUNK_SIZE>> + '_ {
    let len = slice.len();
    let mut a: ArrayVec<_, CHUNK_SIZE> = slice
        .chunks_mut(len / CHUNK_SIZE)
        .map(|chunk| chunk.iter_mut())
        .collect();
    (0..len / CHUNK_SIZE).map(move |_| {
        a.iter_mut()
            .map(|iter| iter.next().unwrap())
            .collect::<ArrayVec<_, CHUNK_SIZE>>()
    })
}

输出:

[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
slice: [0, 1, 2, 0, 1, 2, 0, 1, 2]

杨腾
2023-03-14

所以我总是返回对其内部切片的引用

迭代器trait不支持这一点,因为它的契约允许调用方提取几个值并使用所有值。例如,迭代允许但您的实现不支持以下内容:

// take two values out of the iterator
let a = it.next().unwrap();
let b = it.next().unwrap();

您需要的是一个“借出迭代器”(也称为“流迭代器”),请参见此板条箱。一旦GATs稳定下来,编写借出迭代器将变得容易得多,但它们仍然得不到std::iter::Iterator的支持。

使用标准的迭代器,您可以使用ArrayVec或@Stargateur建议的Vec的等效替代品来避免分配。

 类似资料:
  • 我试图实现这一点:第一个线程打印1,第二个线程打印2,第三个线程打印3,第一个线程打印4等等: 我做到了这一点,并发挥了作用: 输出是这样的: 它达到了目的,但是如果我有两个线程要打印,那么我必须使用更多的如果条件。 任何人都可以建议以更好的形式编写这段代码,以更干净的方式完成任务,这样如果添加更多线程,它就可以扩展。

  • 问题 你想通过数据集合动态的生成交替背景色的列表. 方案 Give templetor access to the int built-in and use modulo to test. code.py web.template.Template.globals['int'] = int template.html <ul> $var i: 0 $for track in tracks:

  • 问题内容: 我想将迭代器分为两个具有交替元素的列表。这是一个可行的解决方案。但是,有没有更简单的方法可以达到相同目的呢? 样本输出: 问题答案: 如果是一个序列,则: 如果是完全通用的可迭代对象,例如生成器:

  • 这是我今天拍的日志: 你知道吗? 提前感谢!

  • 我有一个数组包含玩家的名字,我想按照数组的顺序显示每个问题中玩家的名字,例如arrnames['mark','john','jay'],我想和问题1的mark,问题2的john一起显示。 这是我正在尝试的,但我只得到数组中的最后一个值,我如何修复它?

  • 我有一个数组包含玩家的名字,我想按照数组的顺序显示每个问题中玩家的名字,例如arrnames['mark','john','jay'],我想和问题1的mark,问题2的john一起显示。 这是我正在尝试的,但我只得到数组中的最后一个值,我如何修复它?