Rust中没有映射文字语法.我不知道原因是什么,但我预计,有多个数据 struct 的行为类似于 map (例如BTreeMap
和HashMap
),因此很难 Select 一个.
Rust 1.56
许多集合现在使用From
或Into
从数组参数提供转换:
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
fn main() {
let s = Vec::from([1, 2, 3]);
println!("{:?}", s);
let s = BTreeSet::from([1, 2, 3]);
println!("{:?}", s);
let s = HashSet::from([1, 2, 3]);
println!("{:?}", s);
let s = BTreeMap::from([(1, 2), (3, 4)]);
println!("{:?}", s);
let s = HashMap::from([(1, 2), (3, 4)]);
println!("{:?}", s);
}
对于某些语法,可以将此逻辑包装回宏:
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
macro_rules! collection {
// map-like
($($k:expr => $v:expr),* $(,)?) => {{
core::convert::From::from([$(($k, $v),)*])
}};
// set-like
($($v:expr),* $(,)?) => {{
core::convert::From::from([$($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);
}
Rust 1.51
从Rust 1.51开始,您可以使用按值数组迭代器和FromIterator
来收集到多种集合中:
use std::array::IntoIter;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter::FromIterator;
fn main() {
// Rust 1.53
let s = Vec::from_iter([1, 2, 3]);
println!("{:?}", s);
// Rust 1.51
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);
}
请注意,在Rust 1.53中,并不总是需要std::array::IntoIter
.
对于某些语法,可以将此逻辑包装回宏:
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
macro_rules! collection {
// map-like
($($k:expr => $v:expr),* $(,)?) => {{
use std::iter::{Iterator, IntoIterator};
Iterator::collect(IntoIterator::into_iter([$(($k, $v),)*]))
}};
// set-like
($($v:expr),* $(,)?) => {{
use std::iter::{Iterator, IntoIterator};
Iterator::collect(IntoIterator::into_iter([$($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);
}
这些解决方案避免了不必要的分配和重新分配.
另见:
Previous versions
您可以创建一个宏来完成这项工作,如Why does this rust HashMap macro no longer work?所示.这是一个稍微简化了一点的宏,它有足够的 struct 使其成为runnable in the playground:
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
进行一些无用的重新分配.可以使用更复杂的宏来计算值,但性能方面的好处可能不是大多数使用宏的人都会受益的.