Rust中没有地图文字语法。我不知道确切的原因,但我希望有多个像map一样运作的数据结构(例如BTreeMap
和HashMap
),这将使选择一个困难。
但是,您可以创建一个宏来为您完成工作,如为什么此rust HashMap宏不再起作用?。这是该宏进行了一些简化,并具有足以使其在操场上可运行的结构:
macro_rules! map(
{ $($key:expr => $value:expr),+ } => {
{
let mut m = ::std::collections::HashMap::new();
$(
m.insert($key, $value);
)+
m
}
};
);
fn main() {
let names = map!{ 1 => "one", 2 => "two" };
println!("{} -> {:?}", 1, names.get(&1));
println!("{} -> {:?}", 10, names.get(&10));
}
此宏避免分配不必要的中间体Vec
,但是它不使用,HashMap::with_capacity
因此在HashMap
添加值时可能会有一些无用的重新分配。可以使用更复杂的版本来计算值的宏,但是性能上的好处可能并不是大多数使用该宏的优点。
在锈nightly版本,就能避免双方不必要的分配,也需要有一个宏(和再分配!):
#![feature(array_value_iter)]
use std::array::IntoIter;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter::FromIterator;
fn main() {
let s = Vec::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = BTreeSet::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = HashSet::<_>::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = BTreeMap::from_iter(IntoIter::new([(1, 2), (3, 4)]));
println!("{:?}", s);
let s = HashMap::<_, _>::from_iter(IntoIter::new([(1, 2), (3, 4)]));
println!("{:?}", s);
}
然后,也可以将此逻辑包装回宏:
#![feature(array_value_iter)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
macro_rules! collection {
($($k:expr => $v:expr),* $(,)?) => {
std::iter::Iterator::collect(std::array::IntoIter::new([$(($k, $v),)*]))
};
($($v:expr),* $(,)?) => {
std::iter::Iterator::collect(std::array::IntoIter::new([$($v,)*]))
};
}
fn main() {
let s: Vec<_> = collection![1, 2, 3];
println!("{:?}", s);
let s: BTreeSet<_> = collection! { 1, 2, 3 };
println!("{:?}", s);
let s: HashSet<_> = collection! { 1, 2, 3 };
println!("{:?}", s);
let s: BTreeMap<_, _> = collection! { 1 => 2, 3 => 4 };
println!("{:?}", s);
let s: HashMap<_, _> = collection! { 1 => 2, 3 => 4 };
println!("{:?}", s);
}
也可以看看:
grabbag_macros
箱子里也有一个。您可以在此处查看源代码:github.com/DanielKeep/rust-grabbag/blob/master/grabbag_macros/…。