Skip to content

slice::concat

slice methods · Collections

Level: reference · for working programmers

One line: Flatten a slice of slices — or of strings — into one owned Vec or String.

pub fn concat<Item>(&self) -> <[T] as Concat<Item>>::Output
where
    [T]: Concat<Item>,
    Item: ?Sized,

Stable since 1.0.0.

Two shapes, one method: a [Vec<T>] or [[T; N]] or [&[T]] concatenates into a Vec<T>; a [&str] or [String] concatenates into a String. The Concat trait in the signature is what makes both spellings resolve; read the return type as "the owned, flat version".

It clones the elements — the source is untouched afterwards — and allocates exactly once, having summed the lengths first. The iterator spelling, rows.iter().flatten().cloned().collect(), does the same in more words and without the single pre-sized allocation.

With a separator between the pieces it is join.

Example

slice_concat.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let rows = vec![vec![1, 2], vec![3], vec![]];
    let flat: Vec<i32> = rows.concat();
    println!("{flat:?}");

    // Strings: a slice of &str or of String becomes one String.
    let parts = ["ab", "cd", "ef"];
    let s: String = parts.concat();
    println!("{s}");
    let owned = vec![String::from("x"), String::from("y")];
    println!("{}", owned.concat());

    // It clones: the rows are still here.
    println!("{rows:?}");

    // Arrays of arrays flatten the same way.
    let grid = [[1, 2], [3, 4]];
    println!("{:?}", grid.concat());

    // The iterator spelling of the same thing.
    let via_iter: Vec<i32> = rows.iter().flatten().copied().collect();
    println!("{via_iter:?}");
}

Verified output of slice_concat.rs — regenerated by tools/run_examples.py, never hand-typed.

[1, 2, 3]
abcdef
xy
[[1, 2], [3], []]
[1, 2, 3, 4]
[1, 2, 3]

See also

slice::concat in the standard library ↗