【问题标题】:How to get every subset of a vector in Rust?如何在 Rust 中获取向量的每个子集?
【发布时间】: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


    【解决方案1】:

    您要搜索的内容称为向量的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&lt;Vec&lt;&amp;T&gt;&gt; 来避免 Clone 绑定。
    • @MatthieuM。确实!很好的收获,感谢您的提示。 :)
    【解决方案2】:

    如果输出元素的顺序不重要,并且像这样的输出:[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]] 是可以接受的,你可以这样做:

    基本思路很简单:

    1. 从一个空集开始:[[]]

    2. 将所有元素复制到一个临时变量,该变量将通过将第一个元素 (1) 添加到每个子集来更新 -> [[1]] 并将其添加到原始向量:[[], [1]]

    3. 对第二个元素 (2) 执行第 2 步:[[], [1], [2], [1,2]]

    4. 对第三个元素 (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);
    
    }
    

    【讨论】:

      【解决方案3】:

      这是一个使用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);
      }
      

      【讨论】:

      • 更多惯用的 rust 会删除子集中的返回状态,因此它是隐式的。不过看起来还不错。我喜欢在那里使用combinations,它使实际逻辑保持简单。
      • @timlyo 谢谢,'删除子集中的返回状态'是什么意思?
      • 抱歉打错字了。我的意思是删除return 声明。如果您删除 return 和分号,那么它将被转换为隐式返回,因此它看起来像这样 play.rust-lang.org/…
      猜你喜欢
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 2020-12-28
      相关资源
      最近更新 更多