首页 文章

Rust是否具有Python的字典理解语法?

提问于
浏览
0

如何翻译下面的Python,其中读取了几个文件,并且它们的内容被用作字典的值(文件名为键),以及Rust?

countries = {region: open("{}.txt".format(region)).read() for region in ["canada", "usa", "mexico"]}

我的尝试如下所示,但我想知道是否可以使用单行,惯用的解决方案 .

use std::{
    fs::File,
    io::{prelude::*, BufReader},
    path::Path,
    collections::HashMap,
};

macro_rules! map(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = HashMap::new();
            $(
                m.insert($key, $value);
            )+
            m
        }
     };
);

fn lines_from_file<P>(filename: P) -> Vec<String>
where
    P: AsRef<Path>,
{
    let file = File::open(filename).expect("no such file");
    let buf = BufReader::new(file);
    buf.lines()
        .map(|l| l.expect("Could not parse line"))
        .collect()
}

fn main() {
    let _countries = map!{ "canada" => lines_from_file("canada.txt"),
                           "usa"    => lines_from_file("usa.txt"),
                           "mexico" => lines_from_file("mexico.txt") };
}

2 回答

  • 4

    Rust的迭代器有 map / filter / collect 方法,足以完成Python的理解所能做的任何事情 . 您可以在对的迭代器上使用 collect 创建 HashMap ,但 collect 可以返回各种类型的集合,因此您可能必须指定所需的类型 .

    例如,

    use std::collections::HashMap;
    
    fn main() {
        println!(
            "{:?}",
            (1..5).map(|i| (i + i, i * i)).collect::<HashMap<_, _>>()
        );
    }
    

    大致相当于Python

    print({i+i: i*i for i in range(1, 5)})
    

    虽然从概念上讲,它实际上更接近于

    print("{!r}".format(dict(map(lambda i: (i+i, i*i), range(1, 5)))))
    
  • 1

    Python的理解只是for循环和累加器的糖 . Rust有macros - 你可以制作你想要的任何糖 .

    拿这个简单的Python例子,

    print({i+i: i*i for i in range(1, 5)})
    

    您可以轻松地将其重写为循环和累加器:

    map = {}
    for i in range(1, 5):
        map[i+i] = i*i
    print(map)
    

    你可以在Rust中以同样的方式完成它 .

    use std::collections::HashMap;
    
    fn main() {
        let mut hm = HashMap::new();
        for i in 1..5 {
            hm.insert(i + i, i * i);
        }
        println!("{:?}", hm);
    }
    

    您可以使用宏来重写此表单 .

    use std::collections::HashMap;
    macro_rules! hashcomp {
        ($name:ident = $k:expr => $v:expr; for $i:ident in $itr:expr) => {
            let mut $name = HashMap::new();
            for $i in $itr {
                $name.insert($k, $v);
            }
        };
    }
    

    使用它时,生成的代码更紧凑 . 这种分隔符标记的选择使它类似于Python .

    fn main() {
        hashcomp!(hm = i+i => i*i; for i in 1..5);
        println!("{:?}", hm);
    }
    

    这只是一个可以处理单个循环的基本示例 . Python的理解也可以有过滤器和额外的循环,但更高级的宏也可能会这样做 .

相关问题