rust - 将大小为 N 的向量转换为固定大小的数组长度 N 超过 32
问题描述
编辑:这个问题与 Rust >= 1.47的版本无关,因为“const generics”已经开始实施。
我正在尝试在 Rust 中实现数独求解器以用于学习目的。我正在尝试创建一个具有固定大小(81)的Cell
s 数组(即Copy
)的板,但我似乎无法让它工作。我可以创建一行 9 ,所以我想我遇到了这样一个问题,即这种转换Cell
只有 for up 32 的泛型。TryFrom
Cell
现在看起来像这样:
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
这有效:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = std::iter::repeat(0)
.zip(0..9u8)
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 9]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
但这不会:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 81]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
我尝试使用以下代码std
作为指南:
impl TryFrom<Box<[Cell]>> for Box<[Cell; 81]> {
type Error = Box<[Cell]>;
fn try_from(boxed_slice: Box<[Cell]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == 81 {
Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [Cell; 91]) })
} else {
Err(boxed_slice)
}
}
}
但这会遇到一个错误conflicting implementations of trait
,我认为这是有道理的。
我知道我可以使用 aVec
或做类似的事情,[[Cell; 9]; 9]
但我真的很想了解发生了什么。在试图弄清楚这一点时,我看到了许多类似的问题,人们试图使用未实现的类型,Copy
这就是问题所在,但这里不是这种情况,我不知道如何使这项工作.
解决方案
该特征FromIterator
没有为切片实现,您可以将其包装在一个类型中并自己实现它:
use core::iter::FromIterator;
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
#[derive(Debug)]
struct Sudoku(Box<[Cell]>);
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = Vec::new();
for cell in iter {
v.push(cell)
}
Sudoku(v.into_boxed_slice())
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{:#?}", cells);
}
编辑:
您还可以针对数组的特定大小来实现它。对于数独来说,这应该没问题,但总的来说,您希望事情以更一般的方式工作。除了固定大小,您还可以编写一个宏来编写任何给定大小的实现。
例子:
use core::iter::FromIterator;
use std::fmt;
#[derive(Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
impl fmt::Display for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Cell: ({}, {})", self.row, self.column)
}
}
struct Sudoku([Cell; 81]);
impl fmt::Display for Sudoku {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for cell in self.0.iter() {
write!(f, "{}\n", cell)?;
}
Ok(())
}
}
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = [Cell {row: 0, column: 0}; 81];
for (i, cell) in (0..81).zip(iter) {
v[i] = cell;
}
Sudoku(v)
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{}", cells);
}
推荐阅读
- sublimetext3 - 我如何知道创建键绑定快捷方式以在 Sublime Text 3 中运行自定义包的参数?
- java - 扫描二维码并使用 p:photoCam 对其进行解码
- shell - 在将数据插入 Hive 表之前加载 xml 文件并映射给定的列
- angular - 将 Typescript 类转换为字符串?
- python - 从 tkinter 组合框字典中获取 VALUE
- git - 如何删除特定作者的所有提交/代码?
- django - django 如何在请求/响应周期中处理 cached_property 失效?
- python - 为什么它有双重 __init__ 功能?
- android - 获取从相机传感器到当前设备方向的相对旋转
- azure - 无法删除自定义角色定义 - 现有角色分配