交换 HashMap 的两个条目
swapping two entries of a HashMap
我有一个简单的HashMap
;说 HashMap<char, char>
.
有没有办法使用 std::mem::swap
(或任何其他方法)交换此哈希图中的两个元素?
当然有一种使用 get
and then replace them with insert
获取值的简单方法 - 但这会触发哈希器两次(一次用于获取然后用于插入)我正在寻找一种方法来回避第二次哈希调用(更多的是出于好奇而不是性能)。
我尝试的是这个(在几个版本中;none 其中有效 - 正如评论中所说:entry
不会做我期望的,即使我通过了编译器):
use std::collections::HashMap;
use std::mem::swap;
let mut hash_map: HashMap<char, char> = HashMap::default();
hash_map.insert('A', 'Z');
hash_map.insert('B', 'Y');
swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
现在编译器报错了(我明白为什么会报错)
error[E0499]: cannot borrow `hash_map` as mutable more than once at a time
--> tests.rs:103:42
|
103 | swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
| ---- -------- ^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
同样,以这种方式获取两个值也会以大致相同的方式失败:
let mut a_val = hash_map.get_mut(&'A').expect("failed to get A value");
let mut b_val = hash_map.get_mut(&'B').expect("failed to get B value");
swap(&mut a_val, &mut b_val);
有没有办法简单地交换 HashMap
的两个条目?
我看不到任何安全的方法:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert('A', 'Z');
map.insert('B', 'Y');
let a = map.get_mut(&'A').unwrap() as *mut char;
let b = map.get_mut(&'B').unwrap() as *mut char;
unsafe {
std::ptr::swap(a, b);
}
assert_eq!(map.get(&'A'), Some(&'Y'));
assert_eq!(map.get(&'B'), Some(&'Z'));
}
我可以想到一种完全安全的方法来安全地执行此操作,但它的效率非常低:您想要的是获得两个 &mut 值,这意味着 borrowck 需要知道它们是不重叠的。缺少 split_mut
中的内置函数(或专门处理的集合),我看到的唯一方法是可变地迭代整个集合,保留对您感兴趣的项目的引用,然后交换:
let mut h = HashMap::new();
h.insert("a", "a");
h.insert("b", "b");
let mut it = h.iter_mut();
let e0 = it.next().unwrap();
let e1 = it.next().unwrap();
std::mem::swap(e0.1, e1.1);
println!("{:?}", h);
它需要对映射进行线性遍历,直到找到要交换其值的条目。因此,即使这具有完全不散列的优点,edwardw 的答案可能更实用。
我有一个简单的HashMap
;说 HashMap<char, char>
.
有没有办法使用 std::mem::swap
(或任何其他方法)交换此哈希图中的两个元素?
当然有一种使用 get
and then replace them with insert
获取值的简单方法 - 但这会触发哈希器两次(一次用于获取然后用于插入)我正在寻找一种方法来回避第二次哈希调用(更多的是出于好奇而不是性能)。
我尝试的是这个(在几个版本中;none 其中有效 - 正如评论中所说:entry
不会做我期望的,即使我通过了编译器):
use std::collections::HashMap;
use std::mem::swap;
let mut hash_map: HashMap<char, char> = HashMap::default();
hash_map.insert('A', 'Z');
hash_map.insert('B', 'Y');
swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
现在编译器报错了(我明白为什么会报错)
error[E0499]: cannot borrow `hash_map` as mutable more than once at a time
--> tests.rs:103:42
|
103 | swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
| ---- -------- ^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
同样,以这种方式获取两个值也会以大致相同的方式失败:
let mut a_val = hash_map.get_mut(&'A').expect("failed to get A value");
let mut b_val = hash_map.get_mut(&'B').expect("failed to get B value");
swap(&mut a_val, &mut b_val);
有没有办法简单地交换 HashMap
的两个条目?
我看不到任何安全的方法:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert('A', 'Z');
map.insert('B', 'Y');
let a = map.get_mut(&'A').unwrap() as *mut char;
let b = map.get_mut(&'B').unwrap() as *mut char;
unsafe {
std::ptr::swap(a, b);
}
assert_eq!(map.get(&'A'), Some(&'Y'));
assert_eq!(map.get(&'B'), Some(&'Z'));
}
我可以想到一种完全安全的方法来安全地执行此操作,但它的效率非常低:您想要的是获得两个 &mut 值,这意味着 borrowck 需要知道它们是不重叠的。缺少 split_mut
中的内置函数(或专门处理的集合),我看到的唯一方法是可变地迭代整个集合,保留对您感兴趣的项目的引用,然后交换:
let mut h = HashMap::new();
h.insert("a", "a");
h.insert("b", "b");
let mut it = h.iter_mut();
let e0 = it.next().unwrap();
let e1 = it.next().unwrap();
std::mem::swap(e0.1, e1.1);
println!("{:?}", h);
它需要对映射进行线性遍历,直到找到要交换其值的条目。因此,即使这具有完全不散列的优点,edwardw 的答案可能更实用。