Rust 如何收集到数组中?
我想对枚举数组调用Rust 如何收集到数组中?,rust,Rust,我想对枚举数组调用.map(): enum Foo { Value(i32), Nothing, } fn main() { let bar = [1, 2, 3]; let foos = bar.iter().map(|x| Foo::Value(*x)).collect::<[Foo; 3]>(); } enum Foo{ 值(i32), 没有什么, } fn main(){ 设bar=[1,2,3]; 设foos=bar.iter().map
.map()
:
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos = bar.iter().map(|x| Foo::Value(*x)).collect::<[Foo; 3]>();
}
enum Foo{
值(i32),
没有什么,
}
fn main(){
设bar=[1,2,3];
设foos=bar.iter().map(|x | Foo::Value(*x)).collect::();
}
但编译器抱怨:
error[E0277]:不满足特性绑定“[Foo;3]:std::iter::fromtiterator”
-->src/main.rs:8:51
|
8 |让foos=bar.iter().map(|x | Foo::Value(*x)).collect::();
|^^^^无法通过迭代器在`Foo;类型的元素上生成`Foo;3]`类型的集合`
|
=help:trait`std::iter::fromtiterator`未为`[Foo;3]实现`
我如何做到这一点?这是不可能的,因为数组没有实现任何特征。您只能收集到实现<代码>FromIterator特性的类型中(请参见本部分底部的列表)
这是一种语言限制,因为目前不可能对数组的长度进行泛型,并且长度是其类型的一部分。但是,即使有可能,也不太可能在数组上实现来自迭代器的
,,因为如果生成的项数与数组的长度不完全一致,它将不得不惊慌失措。在这种情况下,您可以使用Vec
:
#[派生(调试)]
enum Foo{
值(i32),
没有什么,
}
fn main(){
设bar=[1,2,3];
设foos=bar.iter().map(|&x | Foo::Value(x)).collect::();
println!(“{:?}”,foos);
}
问题实际上在收集中,而不是在地图中
为了能够将迭代的结果收集到一个容器中,这个容器应该实现FromIterator
[T;n]
没有实现来自迭代器的,因为它通常无法实现:要生成[T;n]
您需要准确地提供n
元素,但是在使用来自迭代器的时,您无法保证将输入到您的类型中的元素数量
还有一个困难是,如果没有补充数据,您将不知道现在应该输入数组的哪个索引(以及它是空的还是满的),等等。。。这可以通过在map
之后使用enumerate
来解决(基本上是输入索引),但是如果提供的元素不够或太多,您仍然需要决定该怎么做
因此,不仅目前无法在固定大小的数组上实现FromIterator
;但即使在未来,这似乎也是一个遥远的目标
那么,现在该怎么办?有几种可能性:
- 在调用站点内联转换:
[值(1)、值(2)、值(3)]
,可能需要宏的帮助
- 收集到不同的(可增长的)容器中,例如
Vec
我自己也遇到了这个问题-这里有一个解决方法
您不能使用迭代器中的
,
,但您可以迭代固定大小对象的内容,或者,如果事情更复杂,可以使用索引来分割任何可以访问的内容。无论哪种方式,突变都是可行的
例如,我遇到的问题是类型为[[usize;2];4]
的数组:
fn main() {
// Some input that could come from another function and thus not be mutable
let pairs: [[usize; 2]; 4] = [[0, 0], [0, 1], [1, 1], [1, 0]];
// Copy mutable
let mut foo_pairs = pairs.clone();
for pair in foo_pairs.iter_mut() {
// Do some operation or other on the fixed-size contents of each
pair[0] += 1;
pair[1] -= 1;
}
// Go forth and foo the foo_pairs
}
如果这发生在一个小函数中,在我的书中是可以的。无论哪种方式,最终都会得到一个与同一类型相同的转换值,因此,首先复制整个内容,然后进行变异,这与在闭包中引用一个值并返回它的某个函数的工作量大致相同
请注意,只有当您计划计算相同类型的内容时,这才有效,包括大小/长度。但你使用的锈菌阵列暗示了这一点。(具体地说,您可以Value()
您的Foo
s或Nothing
任意选择它们,并且仍然在数组的类型参数范围内。)虽然由于其他答案所述的原因,您无法直接收集到数组中,但这并不意味着您无法收集到由数组支持的数据结构中,例如:
使用arrayvec::arrayvec;//0.7.0
使用std::数组;
enum Foo{
值(i32),
没有什么,
}
fn main(){
设bar=[1,2,3];
让foos:ArrayVec=array::IntoIter::new(bar).map(Foo::Value.collect();
让_数组=foos
.into_inner()
.unwrap_或_else(| | panic!(“数组未完全填充”);
}
将数组从ArrayVec
中拉出将返回结果
,以处理没有足够的项填充数组的情况;其他答案中讨论的案例。.collect()
构建了可以具有任意长度的数据结构,因为迭代器的项目号通常不受限制。(谢普马斯特的回答已经提供了很多细节)
从映射链获取数据而不分配Vec
或类似内容的一种可能性是将数组的可变引用引入链中。在您的示例中,看起来是这样的:
#[derive(Debug, Clone, Copy)]
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let mut foos = [Foo::Nothing; 3];
bar.iter().map(|x| Foo::Value(*x))
.zip(foos.iter_mut()).for_each(|(b, df)| *df = b);
}
.zip()
使迭代以锁步方式在bar
和foos
上运行——如果foos
分配不足,则较高的bar
将根本不会被映射,如果分配过度,它将保留其原始初始化值。(因此,[Nothing;3]
初始化也需要克隆和复制)。您实际上可以定义一个迭代器来完成此操作
使用std::convert::AsMut;
使用std::default::default;
trait castex:大小+迭代器{
fn铸造(多自)->U{
释放mut:U=U::default();
设arr:&mut[T]=out.as_mut();
对于0..arr.len()中的i{
匹配self.next(){
None=>panic!(“数组未填充”),
一些(v)=>arr[
use arrayvec::ArrayVec; // 0.7.0
use std::array;
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos: ArrayVec<_, 3> = array::IntoIter::new(bar).map(Foo::Value).collect();
let the_array = foos
.into_inner()
.unwrap_or_else(|_| panic!("Array was not completely filled"));
}
#[derive(Debug, Clone, Copy)]
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let mut foos = [Foo::Nothing; 3];
bar.iter().map(|x| Foo::Value(*x))
.zip(foos.iter_mut()).for_each(|(b, df)| *df = b);
}