Is it possible to prepend a value to an array? I know how to concatenate two arrays, but if I have an array and a single value (of the same type as the array), can I prepend this element to the array?
Asked
Active
Viewed 2.2k times
8
-
5"append at the start" = "prepend"; you might have better luck searching with that term – Roger Lipscombe Nov 25 '19 at 21:46
-
Is it not possible to make an array of size one with your prepending value, and just concat with the array? – Brandon Dyer Nov 25 '19 at 21:57
-
@BrandonDyer For *array*? Not at runtime. You could create your own `Arr` type that allocates `N` elements then recreate another one of size `N+1` every time you want to add something... Or you could stop trying to avoid using `Vec` which manages all of that already and cannot be done better (well, maybe vector that is designed to allow inserting lots of elements in front and back by keeping elements in the middle with "padding memory" around them would work better for some cases, even though at that point you're better off using lists) at this point in time with computers we have right now. – Nov 26 '19 at 11:20
2 Answers
8
There is no way to do this in stable Rust; arrays cannot have values added or removed at runtime; their lengths are fixed at compile time.
It’s more likely you want a Vec
and Vec::insert
.
See also:
- How to set a Rust array length dynamically?
- What is the difference between a slice and an array?
- What is the difference between storing a Vec vs a Slice?
- Efficiently insert or replace multiple elements in the middle or at the beginning of a Vec?
In nightly Rust, you can use unstable features to construct a brand new array that's slightly bigger and move all the values over:
// 1.52.0-nightly (2021-03-07 234781afe33d3f339b00)
#![allow(incomplete_features)]
#![feature(const_generics, const_evaluatable_checked)]
use std::{
array::IntoIter,
mem::{self, MaybeUninit},
ptr,
};
fn prepend<T, const N: usize>(a: [T; N], v: T) -> [T; N + 1] {
// # SAFETY
//
// Converting an uninitialized array to an array of
// uninitialized values is always safe.
// https://github.com/rust-lang/rust/issues/80908
let mut xs: [MaybeUninit<T>; N + 1] = unsafe { MaybeUninit::uninit().assume_init() };
let (head, tail) = xs.split_first_mut().unwrap();
*head = MaybeUninit::new(v);
for (x, v) in tail.iter_mut().zip(IntoIter::new(a)) {
*x = MaybeUninit::new(v)
}
// # SAFETY
//
// We are effectively transmuting from an array of filled `MaybeUninit<T>` to
// the array of `T`, but cannot actually use `transmute`:
// https://github.com/rust-lang/rust/issues/61956
unsafe {
let tmp_xs = &mut xs as *mut [MaybeUninit<T>; N + 1] as *mut [T; N + 1];
mem::forget(xs);
ptr::read(tmp_xs)
}
}
fn main() {
let v = prepend([1, 2, 3], 4);
assert_eq!([4, 1, 2, 3], v);
}
See also:

Shepmaster
- 388,571
- 95
- 1,107
- 1,366
-
That's not entirely true, you can set a variable to be an array with size one larger and have the prepended value be the first. – Brandon Dyer Nov 25 '19 at 21:58
-
1@BrandonDyer that's not a generally available solution. Arrays require that all the values be populated at all times. See also [How can I initialize an array using a function?](https://stackoverflow.com/q/36925673/155423). Can you post a playground example demonstrating how you'd do it to make sure we are talking about the same thing? – Shepmaster Nov 25 '19 at 22:00
-
I was making my assumption based on "I know how to concatenate two arrays". If this is true, then it is possible to use the method I described. – Brandon Dyer Nov 25 '19 at 22:24
-
@BrandonDyer I do not believe it to be possible to concatenate two arrays at runtime and result in another array in stable Rust. – Shepmaster Nov 25 '19 at 22:29
-
I am referring to compile-time allocation. Of course, the values from the first array would need to be copied at runtime, but the array itself would be perfectly valid on compile. `let arr1: [T; num]; let arr2: [T; num + 1];` – Brandon Dyer Nov 25 '19 at 22:34
-
@BrandonDyer please provide a playground link showing your solution in action and/or provide an alternate answer. Arrays require that all the values be populated at all times. You cannot declare an array and only partially fill it in. – Shepmaster Nov 25 '19 at 22:41
-
Something like this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3d1c476b9b859a3132e268b6aeb8955b – Brandon Dyer Nov 25 '19 at 23:02
-
Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/203063/discussion-between-shepmaster-and-brandon-dyer). – Shepmaster Nov 25 '19 at 23:33
-4
use phpify::array::array_unshift;
let mut queue = vec!["orange", "banana"];
array_unshift(&mut queue, "apple");
assert_eq!(queue, vec!["apple", "orange", "banana"]);
Reference:https://docs.rs/phpify/0.1.0-beta4/phpify/array/index.html
The other way is writing a function in Rust similar to https://stackoverflow.com/a/8963973/9676346

Manish Srivastava
- 37
- 6
-
1This does not answer the question (uses `Vec` and not array), uses a library for no reason where simple `Vec::insert()` will do, this library is not commonly used at all; and there is also much better answer. – Chayim Friedman Jun 08 '22 at 00:38