algorithm - 试图取消引用 `&` 指针

标签 algorithm pointers rust

出于学习目的,我正尝试在 Rust 中编写 kmeans 的 naif 实现。其中一个步骤如下:我有一个积分收藏xs和另一个点集合centroids .我想对 xs 进行分组基于质心中最近的邻居。也就是说,如果两个点有一个共同的最近邻,则它们属于同一组。

例如在 Scala 中这看起来像

xs groupBy { x => closest(x, centroids) } values 

找不到 groupBy标准库中的方法,我尝试将其编写如下(假设定义了 Pointclosest):

fn clusters(xs: & Vec<Point>, centroids: & Vec<Point>) -> Vec<Vec<Point>> {
  let mut groups: TreeMap<Point, Vec<Point>> = TreeMap::new();

  // for x in xs.iter() {
  //   let y = closest(*x, centroids);
  //   match groups.find(&y) {
  //     Some(mut val) => val.push(*x),
  //     None => {
  //       groups.insert(y, vec![*x]);
  //     },
  //   }
  // }

  let result: Vec<Vec<Point>> = groups.values().map(|x| *x).collect();
  result
}

我已经评论了中心部分,因为我在创建 TreeMap<Point, Vec<Point>> 时已经遇到问题并将其值作为 Vec<Vec<Point>> 返回.有一种方法values在 TreeMap 上,它返回类型为 Map<...> 的迭代器.我试过:

  • 直接返回迭代器,但 Rust 提示说我必须添加一个生命周期说明符,我不确定要使用哪个
  • 将其收集到 Vec 中.问题是迭代器的元素实际上是指向 Vec<Point> 的指针。 ,所以我必须做类似 let result: Vec<& Vec<Point>> = groups.values().collect(); 的事情.同样,Rust 不会让我返回那些指针,因为它们的生命周期太短了
  • 取消引用所有这些指针,如上所示。我认为这是正确的方法,但 Rust 告诉我 error: cannot move out of dereference of &-pointer

返回该 map 值的正确方法是什么?

此外,如果我对中心部分进行反注释,Rust 会阻止我执行 groups.insert(y, vec![*x]);因为groups在模式匹配中被本地借用为不可变引用。我该如何解决这个问题?

最佳答案

您的第一个问题是 values() 返回一个对象,该对象提供到 TreeMap 的不可变投影,但您正试图在 map 调用中将数据移出它。

两种可能的解决方案是: 1)您创建向量的副本。然而,这是昂贵的操作。

let result: Vec<Vec<Point>> = groups.values().map(|x| x.clone()).collect();

2) 您使用 into_iter() 方法来消耗 TreeMap ,您可以自由地将数据移出它。

let result: Vec<Vec<Point>> = groups.into_iter().map(|(p, v)| v).collect();

那么,注释的代码有两个问题。

首先,您必须获得对找到的项目的可变引用,因此您必须调用 find_mut() 而不是 find()。

其次,在 None 分支中,您试图插入到已经借用的 TreeMap 中(通过 find()/find_mut() 调用的结果)。 Rust 不会让你。目前,唯一的选择是在匹配 block 之后推迟插入:

  let should_insert = match groups.find_mut(&y) {
      Some(mut val) => {
        val.push(*x);
        false
      }
      None => {
          true
      },
  };
  if should_insert {
      groups.insert(y, vec![*x]);
  }

编辑:在新版本的 Rust 中有更好的方法:

use std::collections::btree_map::Entry;
match groups.entry(&y) {
    Entry::Occupied(mut view) => { val.get_mut().push(*x); }
    Entry::Vaccant(view) => { view.insert(vec![*x]); }
};

关于algorithm - 试图取消引用 `&` 指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26378178/

相关文章:

c - C 中的简单指针问题 - 错误值

c - 可以在函数内部运行一个 c 数组,只用一个指针作为参数吗?

c++ - libevent:未初始化的结构指针

rust - 简单的 future 示例

methods - 如何在 Rust 中使用方法作为函数指针

rust - 为什么 Rust 的 assert_eq!使用匹配实现?

python - Python中没有所有元素重复的组合

python - 正则表达式比使用 .replace() 更快吗

algorithm - 创建平面图的对偶

algorithm - 使用递归计算数组中对象的数量