如何在数组中添加一个值作为第一个元素?

9

如何在数组开头添加一个值?我知道怎样将两个数组连接起来,但如果我有一个数组和一个单独的值(与数组中的类型相同),我能把这个元素添加到数组的开头吗?


5
“append at the start” 可以翻译为 “prepend”,您可以使用这个术语进行搜索,或许会更容易找到相关内容。 - Roger Lipscombe
你不能使用只包含预先值的大小为1的数组,然后与数组连接吗? - Brandon Dyer
@BrandonDyer 对于array?不是在运行时。你可以创建自己的Arr类型,分配N个元素,然后每次想要添加东西时重新创建一个大小为N+1的数组...或者你可以停止试图避免使用Vec,它已经管理了所有这些,并且不能更好地完成(嗯,也许设计为允许在前面和后面插入大量元素并通过在它们周围保留“填充内存”的元素来保持中间元素的向量在某些情况下会更好,尽管此时最好使用列表)在我们现在拥有的计算机上。 - user11877195
2个回答

8

在稳定版的Rust中无法实现这一点;数组无法在运行时添加或删除值;它们的长度在编译时固定。

更可能的是,您想使用VecVec::insert

另请参见:


在 Rust 的夜间版本中,您可以使用不稳定的功能构建一个略大的全新数组,并将所有值移动到其中:
// 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);
}

另请参阅:


1
@BrandonDyer 这不是一个普遍可用的解决方案。数组要求所有值始终被填充。另请参见如何使用函数初始化数组?。您能否发布一个示例来演示您将如何执行此操作,以确保我们谈论的是同一件事? - Shepmaster
我基于“我知道如何连接两个数组”做出了我的假设。如果这是真的,那么就可以使用我描述的方法。 - Brandon Dyer
@BrandonDyer 我认为在 Rust 中不可能在运行时连接两个数组并得到另一个稳定的数组。 - Shepmaster
我指的是编译时分配。当然,第一个数组中的值需要在运行时复制,但数组本身在编译时就是完全有效的。let arr1: [T; num]; let arr2: [T; num + 1]; - Brandon Dyer
让我们在聊天中继续这个讨论。 - Shepmaster
显示剩余3条评论

-4

1
这并没有回答问题(使用了 Vec 而不是数组),无缘无故地使用了一个库,而简单的 Vec::insert() 就可以解决问题,这个库根本不常用;另外还有更好的答案。 - Chayim Friedman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接