Rust 如何将两个变量之间的双向关系存储为第三个变量?
我有一系列的国家,我想建立这些国家之间的关系,这样国家A和国家B之间的关系总是与国家B和国家A之间的关系相同 例如,日本和厄瓜多尔的关系值为15。我希望能够同时运行Rust 如何将两个变量之间的双向关系存储为第三个变量?,rust,Rust,我有一系列的国家,我想建立这些国家之间的关系,这样国家A和国家B之间的关系总是与国家B和国家A之间的关系相同 例如,日本和厄瓜多尔的关系值为15。我希望能够同时运行get_关系(“日本”、“厄瓜多尔”)和获取关系(“厄瓜多尔”、“日本”)并始终获得15。理想情况下,我不想将这个值存储两次,因为我不想费心让它保持同步 下面是我目前的实验代码。请注意,我将国家存储为的HashMap(名称为字符串,国家为结构),这是出于不相关的原因,主要是因为我可以单独按名称提取所需的国家对象 extern crat
get_关系(“日本”、“厄瓜多尔”)代码>和获取关系(“厄瓜多尔”、“日本”)代码>并始终获得15
。理想情况下,我不想将这个值存储两次,因为我不想费心让它保持同步
下面是我目前的实验代码。请注意,我将国家存储为的HashMap
(名称为字符串,国家为结构)
,这是出于不相关的原因,主要是因为我可以单独按名称提取所需的国家
对象
extern crate rand;
use std::collections::HashMap;
use rand::Rng;
struct Nation;
pub struct NationManager {
nations: HashMap<String, Nation>, // The string is the nation's name
rels: HashMap<String, HashMap<String, i8>>, // Again, both Strings are names
}
impl NationManager {
fn generate_relationships(&mut self) {
let mut random_rel: i8 = rand::thread_rng().gen_range(1, 101);
for (source, _) in &self.nations {
for (target, _) in &self.nations {
if source > target {
self.rels
.get(source)
.expect("ERROR")
.insert(target.clone(), random_rel);
} else if source < target {
self.rels
.get(target)
.expect("ERROR")
.insert(source.clone(), random_rel);
} else {
continue;
}
}
}
}
}
fn main() {}
问题是你使用了错误的方法。不允许您更改结果:
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq,
问题是你使用了错误的方法。不允许您更改结果:
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq,
第一件事:您遇到的问题是get
返回一个不可变的引用,并且您尝试insert
。您可能希望使用get_mut
获取一个可执行insert
的可变引用
但是,我建议修改设计:
存储地图名称->ID
在其他地图中使用ID作为键
此方案的主要优点是数字ID比字符串便宜/高效
pub struct NationManager {
last_id: u32,
name_to_id: HashMap<String, u32>,
relationships: HashMap<(u32, u32), i8>, // (smaller ID, larger ID) -> score
}
注意:实际上,域分析也可以让我们使用更小的ID;你不需要超过65535个国家,所以u16肯定足够了,而且u8
(255个国家)也足够了(联合国注册了193个国家)。第一件事:你的问题是get
返回一个不可变的引用,然后尝试在其中插入。您可能希望使用get_mut
获取一个可执行insert
的可变引用
但是,我建议修改设计:
存储地图名称->ID
在其他地图中使用ID作为键
此方案的主要优点是数字ID比字符串便宜/高效
pub struct NationManager {
last_id: u32,
name_to_id: HashMap<String, u32>,
relationships: HashMap<(u32, u32), i8>, // (smaller ID, larger ID) -> score
}
注意:实际上,域分析也可以让我们使用更小的ID;你需要的国家不应该超过65535个,因此u16肯定足够了,而且u8(255个国家)也足够了(联合国注册了193个国家)。一个不相关的注释:与其使用.expect(“ERROR”)
,不如使用.unwrap()
,而不是,这对眼睛更容易。expect()
的要点是提供有意义的错误消息。编译器提供的实际错误消息是什么?“由于所有权问题而无法编译”不是很有用。@user4815162342我重申,“当前实验代码”@E_net4“不能以可变方式借用”,指向self.rels.get(target.expect(“ERROR”)
。我希望有人能有更好的解决办法。我无法想象我是如何完成这项任务的。请编辑你的问题以包含更多内容。@Quintus:顺便问一下,随机生成不应该在循环中吗?似乎所有国家的关系得分都是相等的。一个不相关的注意事项:与其使用.expect(“ERROR”)
,不如使用.unwrap()
,这样看起来更容易。expect()
的要点是提供有意义的错误消息。编译器提供的实际错误消息是什么?“由于所有权问题而无法编译”不是很有用。@user4815162342我重申,“当前实验代码”@E_net4“不能以可变方式借用”,指向self.rels.get(target.expect(“ERROR”)
。我希望有人能有更好的解决办法。我无法想象我是如何完成这项任务的。请编辑你的问题以包含更多内容。@Quintus:顺便问一下,随机生成不应该在循环中吗?似乎所有国家在这方面的关系得分都是相等的。“你应该需要超过65535个国家”?:)这是一个非常聪明的解决方案,谢谢!使用数字肯定会让我更容易理解。因此,对于getter,我可以假设任意两个国家之间的关系存储在(低ID,高ID)
元组中,对吗?另外,感谢您指出了get_mut
方法-我仍然在用u8
/u16
//u32
-88字节来概括Rust.FWIW中的所有权。@Shepmaster:aVec
和aVec
也将具有相同的大小,但其堆分配的数组将具有不同的大小。这同样适用于HashMap
(baring padding)。当然,由于缓冲区是内部的,所以检查起来有点困难,而且我不确定HashMap
是否利用了较小的键。BLUS的OrderedMap将使用单独的Vec
“您应该需要超过65535个国家”?:)这是一个非常聪明的解决方案,谢谢!使用数字肯定会让我更容易理解。因此,对于getter,我可以假设任意两个国家之间的关系存储在(低ID,高ID)
元组中,对吗?另外,感谢您指出了get_mut
方法-我仍然在用u8
/u16
//u32
-88字节来概括Rust.FWIW中的所有权。@Shepmaster:aVec
和aVec
也将具有相同的大小,但其堆分配的数组将具有不同的大小。这同样适用于HashMap
(baring padding)。属于