如何在Rust中连接两个切片?

时间:2016-10-20 12:14:28

标签: rust

我想从向量中获取x个第一个和最后一个元素并将它们连接起来。我有以下代码:

fn main() {
    let v = (0u64 .. 10).collect::<Vec<_>>();
    let l = v.len();
    vec![v.iter().take(3), v.iter().skip(l-3)];
}

这给了我错误

error[E0308]: mismatched types
 --> <anon>:4:28
  |
4 |     vec![v.iter().take(3), v.iter().skip(l-3)];
  |                            ^^^^^^^^^^^^^^^^^^ expected struct `std::iter::Take`, found struct `std::iter::Skip`
<anon>:4:5: 4:48 note: in this expansion of vec! (defined in <std macros>)
  |
  = note: expected type `std::iter::Take<std::slice::Iter<'_, u64>>`
  = note:    found type `std::iter::Skip<std::slice::Iter<'_, u64>>`

如何获取vec的{​​{1}}?我正在使用Rust 1.12。

3 个答案:

答案 0 :(得分:16)

在一片切片上使用.concat()

fn main() {
    let v = (0u64 .. 10).collect::<Vec<_>>();
    let l = v.len();
    let first_and_last = [&v[..3], &v[l - 3..]].concat();
    println!("{:?}", first_and_last);
    // The output is `[0, 1, 2, 7, 8, 9]`
}

这会创建一个新的向量,它可以使用任意数量的切片。

(Playground link)

答案 1 :(得分:13)

Ok, first of all, your initial sequence definition is wrong. You say you want 1, 2, 3, 8, 9, 10 as output, so it should look like:

    let v = (1u64 .. 11).collect::<Vec<_>>();

Next, you say you want to concatenate slices, so let's actually use slices:

    let head = &v[..3];
    let tail = &v[l-3..];

At this point, it's really down to which approach you like the most. You can turn those slices into iterators, chain, then collect...

    let v2: Vec<_> = head.iter().chain(tail.iter()).collect();

...or make a vec and extend it with the slices directly...

    let mut v3 = vec![];
    v3.extend_from_slice(head);
    v3.extend_from_slice(tail);

...or extend using more general iterators (which will become equivalent in the future with specialisation, but I don't believe it's as efficient just yet)...

    let mut v4: Vec<u64> = vec![];
    v4.extend(head);
    v4.extend(tail);

...or you could use Vec::with_capacity and push in a loop, or do the chained iterator thing, but using extend... but I have to stop at some point.

Full example code:

fn main() {
    let v = (1u64 .. 11).collect::<Vec<_>>();
    let l = v.len();

    let head = &v[..3];
    let tail = &v[l-3..];

    println!("head: {:?}", head);
    println!("tail: {:?}", tail);

    let v2: Vec<_> = head.iter().chain(tail.iter()).collect();
    println!("v2: {:?}", v2);

    let mut v3 = vec![];
    v3.extend_from_slice(head);
    v3.extend_from_slice(tail);
    println!("v3: {:?}", v3);

    // Explicit type to help inference.
    let mut v4: Vec<u64> = vec![];
    v4.extend(head);
    v4.extend(tail);
    println!("v4: {:?}", v4);
}

答案 2 :(得分:5)

您应collect() take() extend() collect() skip()的{​​{1}}结果let mut p1 = v.iter().take(3).collect::<Vec<_>>(); let p2 = v.iter().skip(l-3); p1.extend(p2); println!("{:?}", p1); 的结果:{/ 1}

skip()

修改:正如Neikos所说,您甚至不需要收集extend()的结果,因为IntoIterator接受实施Skip的参数({ {1}},因为它是Iterator)。

编辑2 :但你的数字有点偏;为了获得1, 2, 3, 8, 9, 10,您应该声明v如下:

let v = (1u64 .. 11).collect::<Vec<_>>();

由于Range是左关闭和右开。