Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.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
Vector 有没有更有效的方法来调整以矢量表示的二维网格的大小?_Vector_Memory Management_Rust - Fatal编程技术网

Vector 有没有更有效的方法来调整以矢量表示的二维网格的大小?

Vector 有没有更有效的方法来调整以矢量表示的二维网格的大小?,vector,memory-management,rust,Vector,Memory Management,Rust,我有一个包含由单个Vec表示的二维网格的结构,因为wasm_bindgen不支持要简单地减少分配数量,可以让传递到flat_map的闭包返回迭代器而不是Vec: 也就是说,对于每个块,创建一个迭代器,该迭代器生成块的复制内容,后跟一个0的重复字符串,并将其截断为总大小new_width。这不需要创建任何VEC来存储中间结果,因此它分配的。。。很有可能 这没关系,但可能会更好。FlatMap无法知道内部迭代器的大小,因此它没有给出有用的大小提示(参见类似示例)。这意味着上述解决方案中的Vec开始为

我有一个包含由单个Vec表示的二维网格的结构,因为wasm_bindgen不支持要简单地减少分配数量,可以让传递到flat_map的闭包返回迭代器而不是Vec:

也就是说,对于每个块,创建一个迭代器,该迭代器生成块的复制内容,后跟一个0的重复字符串,并将其截断为总大小new_width。这不需要创建任何VEC来存储中间结果,因此它分配的。。。很有可能

这没关系,但可能会更好。FlatMap无法知道内部迭代器的大小,因此它没有给出有用的大小提示(参见类似示例)。这意味着上述解决方案中的Vec开始为空,可能需要重新分配,并复制其内容数次,然后才能足够大。相反,我们可以先使用Vec::with_capacity来保留正确的空间量,并扩展向量而不是将其收集到其中:

pub fn set_width(&mut self, new_width: usize) {
    use std::iter::repeat;
    let mut new_grid = Vec::with_capacity(self.grid.len() / self.width * new_width);
    for chunk in self.grid.chunks_exact(self.width) {
        new_grid.extend(chunk.iter().copied().chain(repeat(0)).take(new_width));
    }
    self.grid = new_grid;

    self.width = new_width;
}

也可以就地调整网格的大小,最多一次重新分配通常会重用现有网格。然而,该算法要复杂得多。上面是我编写set_width的方法,除非它被证明是一个瓶颈。

要简单地减少分配数量,可以让传递给flat_map的闭包返回迭代器而不是Vec:

也就是说,对于每个块,创建一个迭代器,该迭代器生成块的复制内容,后跟一个0的重复字符串,并将其截断为总大小new_width。这不需要创建任何VEC来存储中间结果,因此它分配的。。。很有可能

这没关系,但可能会更好。FlatMap无法知道内部迭代器的大小,因此它没有给出有用的大小提示(参见类似示例)。这意味着上述解决方案中的Vec开始为空,可能需要重新分配,并复制其内容数次,然后才能足够大。相反,我们可以先使用Vec::with_capacity来保留正确的空间量,并扩展向量而不是将其收集到其中:

pub fn set_width(&mut self, new_width: usize) {
    use std::iter::repeat;
    let mut new_grid = Vec::with_capacity(self.grid.len() / self.width * new_width);
    for chunk in self.grid.chunks_exact(self.width) {
        new_grid.extend(chunk.iter().copied().chain(repeat(0)).take(new_width));
    }
    self.grid = new_grid;

    self.width = new_width;
}

也可以就地调整网格的大小,最多一次重新分配通常会重用现有网格。然而,该算法要复杂得多。以上是我将如何编写set_width,除非它被证明是一个瓶颈。

网格点的顺序与您相关吗?如果不是,我将使用从2D到1D的不同序列化:

假设你有这样一个矩阵:

1 2 5
3 4 6
7 8 9
因此,如果矩阵变得更宽或更高,则根本不移动较小位置的索引,而是将新条目作为新的“层”附加到已有矩阵周围

您可以将其序列化为[1,2,3,4,5,6,7,8,9]

假设所有索引和坐标从0开始:
如果你想访问n,m,你可以通过计算maxn,m找到矩阵值所在的“层”。第n个“层”将从索引位置n*n开始。在该层中,您可以在右侧添加的零件中找到前n个元素,在底部添加的行中找到以下n+1个元素。

网格点的顺序是否与您相关?如果不是,我将使用从2D到1D的不同序列化:

假设你有这样一个矩阵:

1 2 5
3 4 6
7 8 9
因此,如果矩阵变得更宽或更高,则根本不移动较小位置的索引,而是将新条目作为新的“层”附加到已有矩阵周围

您可以将其序列化为[1,2,3,4,5,6,7,8,9]

假设所有索引和坐标从0开始:
如果你想访问n,m,你可以通过计算maxn,m找到矩阵值所在的“层”。第n个“层”将从索引位置n*n开始。在该层中,您可以找到右侧添加的零件中的前n个元素,以及底部添加的行中的以下n+1个元素。

尝试调整网格宽度的大小,仅在new_width>self.width时保留一次新内存:

我曾考虑在Vec的反向行上迭代,并使用splice插入/删除值,但我不确定它是否更有效

使用接头:


尝试在适当位置调整网格宽度,仅在new_width>self.width时保留一次新内存:

我曾考虑在Vec的反向行上迭代,并使用splice插入/删除值,但我不确定它是否更有效

使用接头:


我希望能够调整网格的宽度-是否也要调整高度。另一种方法是使用n维数组库。例如:@Shepmaster我现在可以使用self.grid.resizeself.width*new_height调整高度,0可添加或删除Vec末端的行。谢谢你的文章,我得多读一些关于这个话题的文章
!如果可以更改为a,则可以在O1中减小宽度,并将其增加回原来的宽度或更小。O1我希望能够调整网格的宽度-是否也要调整高度。另一种方法是使用n维数组库。例如:@Shepmaster我现在可以使用self.grid.resizeself.width*new_height调整高度,0可添加或删除Vec末端的行。谢谢你的文章,我将不得不阅读更多关于这个主题的文章!如果您可以更改为a,则可以在O1中减小宽度,并将其增加回原来的宽度或更小,这是一个很酷的想法,但它仅支持方形或近似方形矩阵,对吗?@trentcl如果它不是完全正方形,你可以将高度和宽度保留在单独的变量中,忽略你不需要的索引。如果矩阵非常不对称,您可能会修改序列化为其他矩阵的方式。这是一个很酷的想法,但它只支持正方形或近似正方形的矩阵,对吗?@trentcl如果它不完全是正方形,您可以将高度和宽度保留在单独的变量中,忽略不需要的索引。如果矩阵非常不对称,您可能会修改序列化为其他矩阵的方式。
1 2 5
3 4 6
7 8 9
use std::{cmp::Ordering, iter};

pub fn set_width(&mut self, new_width: usize) {
    match new_width.cmp(&self.width) {
        Ordering::Greater => {
            let width_diff = new_width - self.width;
            self.grid.reserve_exact(width_diff * self.height);

            for _ in 0..self.height {
                self.grid.extend(iter::repeat(0).take(width_diff));
                self.grid.rotate_right(new_width);
            }
        }

        Ordering::Less => {
            let width_diff = self.width - new_width;

            for _ in 0..self.height {
                self.grid.truncate(self.grid.len() - width_diff);
                self.grid.rotate_right(new_width);
            }
        }

        Ordering::Equal => (),
    }

    self.width = new_width;
}
use std::{cmp::Ordering, iter};

pub fn set_width(&mut self, new_width: usize) {
    match new_width.cmp(&self.width) {
        Ordering::Greater => {
            let width_diff = new_width - self.width;
            let width = self.width;
            self.grid.reserve_exact(width_diff * self.height);

            for i in (0..self.height).rev().map(|n| n * width + width) {
                self.grid.splice(i..i, iter::repeat(0).take(width_diff));
            }
        }

        Ordering::Less => {
            let width_diff = self.width - new_width;
            let width = self.width;
            for (start, end) in (1..=self.height)
                .rev()
                .map(|n| (n * width - width_diff, n * width))
            {
                self.grid.splice(start..end, iter::empty());
            }
        }

        Ordering::Equal => (),
    }

    self.width = new_width;
}