#comprehension #hash-map #python #list #set #macro #collection

understand

Python样式的列表、集合和哈希表推导式通过宏实现

2 个版本

0.1.1 2024年3月11日
0.1.0 2024年3月11日

#2125 in 数据结构

MIT/Apache

20KB
313

理解

Rust中通过宏实现的类似于Python的列表、集合和哈希表推导式。


lib.rs:

推导式

尽可能高效地为Rust实现类似于Python的列表、集合和哈希表推导式。

由于Python处理推导式的方式,一对一的翻译是不可能的,至少不能不依赖于克隆一切。当使用这个库时,是否克隆取决于用户。

遵守Rust的所有权和借用规则,通过值传递将消耗集合。

comp!返回一个元素迭代器。compco!包含一个.collect()调用。

示例

基本数组推导式

let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let y: Vec<_> = comp![2*x, for x in v].collect();
assert_eq!(y, vec![2, 4,6, 8, 10, 12, 14, 16, 18, 20]);

嵌套数组推导式

let v = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
let y: Vec<_> = comp![2*p, for x in v, for p in x].collect();
assert_eq!(y, vec![2, 4, 6, 8, 10, 12, 14, 16, 18]);

创建两个数组的组合,必须使用clone!

let v = vec![1, 2];
let z = vec![3,4];
let y: Vec<_> = comp![(x,y), for x in v, for y in z.clone()].collect();
assert_eq!(y,vec![(1,3),(1,4),(2,3),(2,4)]);

使用过滤器创建一个向量,该向量包含所有小于3的3个索引,它们的和为4。

let y: Vec<_> = comp![vec![i, j, k], for i in 0..3, for j in 0..3, for k in 0..3, if i+j+k == 4].collect();
assert_eq!(y,vec![[0,2,2],[1,1,2],[1,2,1],[2,0,2],[2,1,1],[2,2,0]]);

基本哈希表推导式

let v = vec![1, 2, 3, 4];
let y: HashMap<_,_> = comp!{x=>2*x, for x in v}.collect();
assert_eq!(y, HashMap::from([(1, 2), (2, 4), (3, 6), (4, 8)]));

哈希表推导式也可以嵌套使用,并使用过滤器或特殊的=>语法。

使用嵌套推导式时特殊的'=>'语法,在内部循环上进行操作。例如,将第一个变量作为值分配给数组中的其他数字作为键。

 # use std::collections::HashMap;
 # use comprehend::comp;
 let v: Vec<Vec<_>> = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
 #[allow(redundant_semicolons)]
 let y: HashMap<i32,i32> =
 comp![p=>z.unwrap(), for x in v => {let mut y = x.into_iter(); let z = y.next();}, for p in y].collect();
 assert_eq!(y, HashMap::from([(2, 1), (3, 1), (5, 4), (6, 4), (8, 7), (9, 7)]));

这将相当于以下内容

let v: Vec<Vec<_>> = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
#[allow(redundant_semicolons)]
let y: HashMap<i32,i32> =
comp![{let mut y = x.into_iter(); let z = y.next(); comp![p=>z.unwrap(),for p in y]}, for x in v].flatten().collect();
assert_eq!(y, HashMap::from([(2, 1), (3, 1), (5, 4), (6, 4), (8, 7), (9, 7)]));

无运行时依赖