【发布时间】:2016-11-21 11:24:21
【问题描述】:
在 Rust 中获取向量的每个子集的最简单/最惯用的方法是什么?
let v = vec![1,2,3];
assert_eq!(subsets(v), [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]);
【问题讨论】:
标签: rust
在 Rust 中获取向量的每个子集的最简单/最惯用的方法是什么?
let v = vec![1,2,3];
assert_eq!(subsets(v), [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]);
【问题讨论】:
标签: rust
您要搜索的内容称为向量的powerset。
这是生成向量切片的幂集的代码。
fn powerset<T>(s: &[T]) -> Vec<Vec<T>> where T: Clone {
(0..2usize.pow(s.len() as u32)).map(|i| {
s.iter().enumerate().filter(|&(t, _)| (i >> t) % 2 == 1)
.map(|(_, element)| element.clone())
.collect()
}).collect()
}
fn main() {
let v = vec![1,2,3];
println!("{:?}", v);
let pset = powerset(&v);
println!("{:?}", pset);
}
看到它在行动here。
如果你想要一个引用向量来防止复制,你可以做一个简单的改变:
fn powerset<T>(s: &[T]) -> Vec<Vec<&T>> {
(0..2usize.pow(s.len() as u32)).map(|i| {
s.iter().enumerate().filter(|&(t, _)| (i >> t) % 2 == 1)
.map(|(_, element)| element)
.collect()
}).collect()
}
请参阅here 了解要点。
【讨论】:
Vec<Vec<&T>> 来避免 Clone 绑定。
如果输出元素的顺序不重要,并且像这样的输出:[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]] 是可以接受的,你可以这样做:
基本思路很简单:
从一个空集开始:[[]]
将所有元素复制到一个临时变量,该变量将通过将第一个元素 (1) 添加到每个子集来更新 -> [[1]] 并将其添加到原始向量:[[], [1]]
对第二个元素 (2) 执行第 2 步:[[], [1], [2], [1,2]]
对第三个元素 (3) 执行第 2 步:[[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]]
例如:
fn powerset(s: &[i32]) -> Vec<Vec<i32>> {
let mut subsets: Vec<Vec<i32>> = vec![];
let empty: Vec<i32> = vec![];
subsets.push(empty);
let mut updated: Vec<Vec<i32>> = vec![];
for ele in s {
for mut sub in subsets.clone() {
sub.push(*ele);
updated.push(sub);
}
subsets.append(&mut updated);
}
subsets
}
fn main() {
let my_vec: Vec<i32> = vec![1,2,3];
let subs = powerset(&my_vec);
println!("{:?}", subs);
}
【讨论】:
这是一个使用itertools crate 的更实用的解决方案。
我是 Rust 的新手,所以仅供参考,我关于克隆/借用/所有权/等的决定可能不是最好的,但希望实现的要点是有帮助的。
use itertools::Itertools;
fn subsets<T: Clone>(items: Vec<T>) -> Vec<Vec<T>> {
(0..=items.len())
.map(|count| items.clone().into_iter().combinations(count))
.flatten()
.collect()
}
fn main() {
// for example ...
let it = subsets(vec![12, 24, 36]);
println!("{:?}", it);
}
【讨论】:
combinations,它使实际逻辑保持简单。
return 声明。如果您删除 return 和分号,那么它将被转换为隐式返回,因此它看起来像这样 play.rust-lang.org/…