有没有办法将迭代器解压缩成元组?

时间:2015-04-08 02:29:22

标签: rust

有没有办法完成以下内容:

let v = vec![1, 2, 3];
let (a, b) = v.iter().take(2);

最后是a = 1b = 2

我知道我可以使用矢量,但我想命名变量。

4 个答案:

答案 0 :(得分:11)

这可能不是你要求的,但我想你很少想要将任意大的矢量转换为元组。如果您只想将矢量的前几个元素提取到元组中,则可以使用夜间实验功能切片模式匹配来实现:

#![feature(slice_patterns)]

fn main() {
    let v = vec![1, 2, 3];
    let (a, b) = match &v[..] {
        &[first, second, ref _tail..] => (first, second),
        _ => unreachable!(),
    };
    assert_eq!((a, b), (1, 2));
}

答案 1 :(得分:8)

itertools crate有tuplesnext_tuple等方法可以帮助解决这个问题。

extern crate itertools;

use itertools::Itertools;

fn main() {
    let v = vec![1, 2, 3];
    let (a, b) = v.iter().next_tuple().unwrap();

    assert_eq!(a, &1);
    assert_eq!(b, &2);
}

答案 2 :(得分:3)

我编写了这个丑陋的递归宏,它将Vec转换为元组,因为我想学习一些宏。

macro_rules! tuplet {
    { ($y:ident $(, $x:ident)*) = $v:expr } => {
        let ($y, $($x),*) = tuplet!($v ; 1 ; ($($x),*) ; ($v[0]) );
    };
    { $v:expr ; $j:expr ; ($y:ident $(, $x:ident)*) ; ($($a:expr),*) } => {
        tuplet!( $v ; $j+1 ; ($($x),*) ; ($($a),*,$v[$j]) )
    };
    { $v:expr ; $j:expr ; () ; $accu:expr } => {
        $accu
    }
}

我是新手,可能非常糟糕,所以最有可能做到这一点。这只是一个概念证明。它允许你写:

fn main() {
    let v = vec![1, 2, 3];
    tuplet!((a, b, c) = v);

    assert_eq!(a, 1);
    assert_eq!(b, 2);
    assert_eq!(c, 3);
}

在该宏定义的某处,您可以找到$v[$j]部分,如果要将其用于迭代器,可以用$v.nth($j)替换它。

答案 3 :(得分:1)

gcp处于正确的轨道;他的回答对我来说似乎是正确的。

不过,我将提供一个更具说服力的示例,因为OP似乎在想知道他要求的内容是否值得(“我想不出足够充分的理由将此功能作为可能。”)。请查看下面的Person::from_csv函数:

use itertools::Itertools;

#[derive(Debug)]
struct Person<'a> {
    first: &'a str,
    last:  &'a str,
}

impl<'a> Person<'a> {
    // Create a Person from a str of form "last,first".
    fn from_csv(s: &'a str) -> Option<Self> {
        s.split(',').collect_tuple().map(
            |(last, first)| Person { first, last }
        )
    }
}

fn main() {
    dbg!(Person::from_csv("Doe"));          // None
    dbg!(Person::from_csv("Doe,John"));     // Some(...)
    dbg!(Person::from_csv("Doe,John,foo")); // None
}

它使用split产生的Iterator并将结果收集到一个元组中,以便我们可以对其进行匹配和解构。如果逗号太多或太少,则不会得到匹配的元组。这段代码很干净,因为collect_tuple使我们可以使用模式匹配和解构。

这里是in the playground