传递引用的正确方法是什么?

时间:2021-07-03 13:20:01

标签: rust reference

我有一个函数可以对两个向量执行多项操作。向量由稍后转换为元组等的结构组成......

我想要的是通过引用改变向量 1 中结构体的值,使向量 1 中的值等于向量 2 中的值。

当你运行程序时,你会更好地明白我的意思。 您将获得以下两行输出:

from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler num_pipeline = Pipeline([('std_scale', StandardScaler())]) transformed_dataframe = num_pipeline.fit_transform(dataframe)

num_col = dataframe.dtypes[df.dtypes != 'object'][dataframe.dtypes != 'bool'].index.to_list() df_num = dataframe[num_col] #1 transformed_df = num_pipeline.fit_transform(dataframe) #2 dataframe[num_col] = transformed_df #3

我想要的是在 new_rows_after.rows.viewentry_id 中还有一个“xxx”。但它仍然包含原始值“yyy”。

有时我似乎没有正确传递引用,但我就是找不到那个地方。

这里是否有经验丰富的 Rust 专家可以看到错误可能在哪里?

感谢您的帮助。

Playground link

1 个答案:

答案 0 :(得分:0)

如果我可以这么说,您的代码非常混乱。我的意思是,如果您希望我们帮助您,您至少可以尝试让我们更轻松地提供帮助。通常有帮助的一件事是:尝试减少示例代码的长度。也许这可以帮助您在未来提出代码的最小版本:http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/ (它实际上是关于 ICE 的最少代码示例,但如果你问我的话,最小化 Rust 示例确实是一件很普遍的事情)。


问题

现在,到实际问题。我不太明白你的完整示例代码,所以我做了什么,我只是将它从 194 行减少到 43 行,只是保留,我认为是你的实际问题。

另外,我发现你的变量名相当混乱。我的意思是,我理解您的问题是,new 应该具有来自 old 的值,但 new 具有其旧值而不是 {{1} 的新值} - 说真的,这只是令人困惑。所以,我使用了一个简单的 oldfoo,然后我们开始:

bar

playground

现在据我所知,在上面的版本中,问题只是 fn main() { let dummy_foo = vec![IndexRow { id: "good".to_string(), }]; let dummy_bar = vec![IndexRow { id: "bad".to_string(), }]; let set_foo = IndexSet { rows: dummy_foo }; let mut set_bar = IndexSet { rows: dummy_bar }; // Should copy ids from set_foo to set_bar copy_ids(&mut set_bar, &set_foo); // Here set_bar still contains "bad" println!("set_bar: {:?}", set_bar); } #[derive(Debug)] pub struct IndexRow { pub id: String, } #[derive(Debug)] pub struct IndexSet { pub rows: Vec<IndexRow>, } /// Copy ids from `src` to `dest` pub fn copy_ids<'a, 'b>(dest: &'a mut IndexSet, src: &'b IndexSet) { // Create tuples each with a dest and src entry let mut tuples: Vec<(&str, &str)> = dest .rows .iter() .zip(src.rows.iter()) .map(|(d, s)| (d.id.as_str(), s.id.as_str())) .collect(); for t in tuples.iter_mut() { let (ref mut dest_id, src_id) = t; // Override dest with src *dest_id = *src_id; } } 中的 id 应该替换为 set_bar 中的 id,但 set_foo 仍然包含旧的 set_bar,因为它打印在 "bad" 的末尾。

解决方案

假设确实如此:问题相当简单。您需要实际更改 ID,即 main。但是,在 String 变量中,您只有不可变的 (tuples) &。因此,str 只是将一个引用替换为另一个引用,并且所有仅在 *dest_id = *src_id 中存储/修改的内容。实际的 tuples 从未被触及,它甚至无法从 String 访问。

因此,您需要做的是:让您自己访问可修改的 (tuples) &mut,然后直接修改 那个 字符串。在这里,您可以替换整个字符串,例如使用 String,或者如果您想确保左侧确实有一个 *dest_id = src_id.to_string(),您可以在其上调用一个只存在于 String 而不是String 喜欢 str

所以,这个版本的 dest_id.replace_range(.., src_id) 做了它应该做的:

copy_ids

full example on playground