了解在 Rust 中收集 `flat_map` 与收集 `map` 之间的细微差别
Understanding the nuances between collecting `flat_map` vs collecting `map` in rust
我正在使用 Advent of Code 学习 Rust。
要解析 day 04 2021,我需要解析以下字符串:
88 67 20 19 15
22 76 86 44 73
7 42 6 69 25
12 68 92 21 75
97 45 13 52 70
75 98 24 18 77
17 93 46 49 13
92 56 97 57 66
44 0 65 54 74
23 6 53 42 20
92 94 9 27 41
73 28 62 90 40
78 3 12 37 32
8 86 91 16 30
84 38 68 11 19
理想情况下,我想生成嵌套向量 Vec<Vec<&str>>
。
我的问题是我不明白为什么下面的代码不起作用。
let bingo_sheet = grids_str
split("\r\n\r\n")
.map(|grid| grid.split_whitespace())
.collect::<Vec<Vec<&str>>>();
我也不明白cargo check的意思。 (好吧,这个特征不存在。但为什么呢?)
error[E0277]: a value of type `Vec<Vec<&str>>` cannot be built from an iterator over elements of type `SplitWhitespace<'_>`
--> src\main.rs:36:10
|
36 | .collect::<Vec<Vec<&str>>>();
| ^^^^^^^ value of type `Vec<Vec<&str>>` cannot be built from `std::iter::Iterator<Item=SplitWhitespace<'_>>`
|
= help: the trait `FromIterator<SplitWhitespace<'_>>` is not implemented for `Vec<Vec<&str>>`
经过一些实验后,flat_map
的这种用法似乎有效。
let bingo_sheet = grids_str
.split("\r\n\r\n")
.flat_map(|grid| grid.split_whitespace())
.collect::<Vec<&str>>();
我不明白这里发生了什么。
flat_map
代码的行为符合预期,但 map
代码并非如此。
在我写这篇文章的时候,这个问题已经在评论中得到了简短的回答,但也许更详细的版本仍然有帮助!
I also don't understand the meaning behind cargo check. (Ok the trait doesn't exist. But why?)
std 提供了经常使用的转换,但它并没有为您完成所有转换。
对 split_whitespace
return 的调用是 SplitWhitespace
struct that implements (in the rest of this I will simply say "is") Iterator
。
对 map
return 的调用是一个 Map
结构,它是其给定函数的 return 类型的迭代器,因此它是一个迭代器,一个迭代器,一个迭代器,一个字符串切片。
因为Map
是一个迭代器,它有一个collect
方法。正如您在文档中所见,如果存在实现 FromIterator<Self::Item>
的 B
,则此方法存在。这个 B
是你的 Vec<Vec<&str>>
而 Self::Item
是 Map
的项目,SplitWhiteSpace
结构。所以 collect
是在问,“Vec<Vec<&str>>
实现了 FromIterator<SplitWhiteSpace>
吗?如果是,我存在,如果不存在,我拒绝存在”。
(FromIterator<SplitWhiteSpace>
并不意味着 Vec<T>
可以由 SplitWhiteSpace
结构构成,而是可以由某种类型 I
构成(或者可以被制作成)项目 SplitWhiteSpace
上的迭代器。)
所以让我们看看 Vec 文档,看看 Vec<Vec<&str>>
是否实现了 FromIterator<SplitWhiteSpace>
。 Vec
does implement FromIterator<T>
but only for Vec<T>
,因此在您的情况下它实现了 FromIterator<Vec<&str>>
,但 collect 要求它实现 FromIterator<SplitWhiteSpace>
。它不会,所以您的代码无法编译。
换句话说,将Map<X>
收集到Vec<Y>
时,X必须等于Y。
这就是在 .map
中添加 collect()
的原因。因为这使它成为 Map<Vec<&str>>
,这意味着类型匹配。 flatmap
也可以工作,因为它创建了一个 FlatMap<&str>
,它的工作方式类似于 Map
,并且可以收集到 Vec<&str>
中。 (flat_map
在其给定函数中不需要 collect
,因为它可以处理其中的迭代器)
我正在使用 Advent of Code 学习 Rust。
要解析 day 04 2021,我需要解析以下字符串:
88 67 20 19 15
22 76 86 44 73
7 42 6 69 25
12 68 92 21 75
97 45 13 52 70
75 98 24 18 77
17 93 46 49 13
92 56 97 57 66
44 0 65 54 74
23 6 53 42 20
92 94 9 27 41
73 28 62 90 40
78 3 12 37 32
8 86 91 16 30
84 38 68 11 19
理想情况下,我想生成嵌套向量 Vec<Vec<&str>>
。
我的问题是我不明白为什么下面的代码不起作用。
let bingo_sheet = grids_str
split("\r\n\r\n")
.map(|grid| grid.split_whitespace())
.collect::<Vec<Vec<&str>>>();
我也不明白cargo check的意思。 (好吧,这个特征不存在。但为什么呢?)
error[E0277]: a value of type `Vec<Vec<&str>>` cannot be built from an iterator over elements of type `SplitWhitespace<'_>`
--> src\main.rs:36:10
|
36 | .collect::<Vec<Vec<&str>>>();
| ^^^^^^^ value of type `Vec<Vec<&str>>` cannot be built from `std::iter::Iterator<Item=SplitWhitespace<'_>>`
|
= help: the trait `FromIterator<SplitWhitespace<'_>>` is not implemented for `Vec<Vec<&str>>`
经过一些实验后,flat_map
的这种用法似乎有效。
let bingo_sheet = grids_str
.split("\r\n\r\n")
.flat_map(|grid| grid.split_whitespace())
.collect::<Vec<&str>>();
我不明白这里发生了什么。
flat_map
代码的行为符合预期,但 map
代码并非如此。
在我写这篇文章的时候,这个问题已经在评论中得到了简短的回答,但也许更详细的版本仍然有帮助!
I also don't understand the meaning behind cargo check. (Ok the trait doesn't exist. But why?)
std 提供了经常使用的转换,但它并没有为您完成所有转换。
对 split_whitespace
return 的调用是 SplitWhitespace
struct that implements (in the rest of this I will simply say "is") Iterator
。
对 map
return 的调用是一个 Map
结构,它是其给定函数的 return 类型的迭代器,因此它是一个迭代器,一个迭代器,一个迭代器,一个字符串切片。
因为Map
是一个迭代器,它有一个collect
方法。正如您在文档中所见,如果存在实现 FromIterator<Self::Item>
的 B
,则此方法存在。这个 B
是你的 Vec<Vec<&str>>
而 Self::Item
是 Map
的项目,SplitWhiteSpace
结构。所以 collect
是在问,“Vec<Vec<&str>>
实现了 FromIterator<SplitWhiteSpace>
吗?如果是,我存在,如果不存在,我拒绝存在”。
(FromIterator<SplitWhiteSpace>
并不意味着 Vec<T>
可以由 SplitWhiteSpace
结构构成,而是可以由某种类型 I
构成(或者可以被制作成)项目 SplitWhiteSpace
上的迭代器。)
所以让我们看看 Vec 文档,看看 Vec<Vec<&str>>
是否实现了 FromIterator<SplitWhiteSpace>
。 Vec
does implement FromIterator<T>
but only for Vec<T>
,因此在您的情况下它实现了 FromIterator<Vec<&str>>
,但 collect 要求它实现 FromIterator<SplitWhiteSpace>
。它不会,所以您的代码无法编译。
换句话说,将Map<X>
收集到Vec<Y>
时,X必须等于Y。
这就是在 .map
中添加 collect()
的原因。因为这使它成为 Map<Vec<&str>>
,这意味着类型匹配。 flatmap
也可以工作,因为它创建了一个 FlatMap<&str>
,它的工作方式类似于 Map
,并且可以收集到 Vec<&str>
中。 (flat_map
在其给定函数中不需要 collect
,因为它可以处理其中的迭代器)