< 返回版块

hzqd 发表于 2021-10-30 22:14

问题简化如下:

use itertools::Itertools; // 0.10.1

fn main() {
    [""].iter().map(|s| (s.to_lowercase(), 1))
        .into_grouping_map_by(|s| s.0);
}

获得编译错误:

error[E0507]: cannot move out of `s.0` which is behind a shared reference
 --> src/main.rs:5:35
  |
5 |         .into_grouping_map_by(|s| s.0);
  |                                   ^^^ move occurs because `s.0` has type `String`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` due to previous error

在这种情况下,clone 是一个简单粗暴的选择;但由于数据量较大,会增加一倍左右的耗时。

我希望能避免 clone 的开销,要怎么做?

评论区

写评论
作者 hzqd 2021-10-31 00:10

问题解决了,感谢解答!

--
👇
苦瓜小仔: 我不知道你真实的意图是什么,但是如果需要计数或者基于位置进行计算,你可以这么写

苦瓜小仔 2021-10-30 23:49

我不知道你真实的意图是什么,但是如果需要计数或者基于位置进行计算,你可以这么写:

use itertools::Itertools;

fn main() {
    let lookup = ["a", "A", "b"]
        .iter()
        .into_grouping_map_by(|s| s.to_lowercase())
        .aggregate(|acc, _, _| Some(acc.unwrap_or(0) + 1));

    println!("{:?}", lookup); // {"a": 2, "b": 1}

    let lookup = ["a", "A", "b"]
        .iter()
        .enumerate() 
        .into_grouping_map_by(|(_, s)| s.to_lowercase())
        .aggregate(|acc, _, (i, _)| Some(acc.unwrap_or(0) + i*2));

    println!("{:?}", lookup); // {"a": 2, "b": 4}
}

--
👇
hzqd: 你曲解了 into_grouping_map_by 的含义,这个是用来分组的,不是用来映射的。

必须先映射,再分组。

--
👇
苦瓜小仔: 仅对此例:

[""].iter().into_grouping_map_by(|s| (s.to_lowercase(), 1));
作者 hzqd 2021-10-30 23:17

你曲解了 into_grouping_map_by 的含义,这个是用来分组的,不是用来映射的。

必须先映射,再分组。

--
👇
苦瓜小仔: 仅对此例:

[""].iter().into_grouping_map_by(|s| (s.to_lowercase(), 1));
作者 hzqd 2021-10-30 23:12

&str 可以通过编译。这里不能通过编译是因为 to_lowercase 返回了 String,而 into_grouping_map_by 会把元组带个引用,于是 String 就变成了共享引用,无法 move

--
👇
gwy15: 你看它源代码就知道 https://docs.rs/itertools/0.10.1/src/itertools/grouping_map.rs.html#27

self.0.next().map(|val| ((self.1)(&val), val))

这里是直接进行一个 (self.1)(&val), val)self.1FnMut(&V) -> K,那这里就不可能用 &str,因为这两个都需要有所有权。

那要避免克隆就必须对你的所有权进行改造,比如用 Arc<str> 或者 Rc<str> 替换 String

苦瓜小仔 2021-10-30 22:59

仅对此例:

[""].iter().into_grouping_map_by(|s| (s.to_lowercase(), 1));
gwy15 2021-10-30 22:37

你看它源代码就知道 https://docs.rs/itertools/0.10.1/src/itertools/grouping_map.rs.html#27

self.0.next().map(|val| ((self.1)(&val), val))

这里是直接进行一个 (self.1)(&val), val)self.1FnMut(&V) -> K,那这里就不可能用 &str,因为这两个都需要有所有权。

那要避免克隆就必须对你的所有权进行改造,比如用 Arc<str> 或者 Rc<str> 替换 String

shaitao 2021-10-30 22:36

iter 换成into_iter

1 共 7 条评论, 1 页