Primitive Type array1.0.0[−]
Expand description
一个固定大小的数组,表示为 [T; N]
,用于元素类型 T
和非负编译时常量大小 N
。
创建数组有两种语法形式:
- 包含每个元素的列表,即
[x, y, z]
。 - 重复表达式
[x; N]
,该数组生成包含x
的N
副本的数组。x
的类型必须为Copy
。
请注意,[expr; 0]
是允许的,并产生一个空数组。
然而,这仍然会计算 expr
,并立即丢弃结果值,因此请注意副作用。
如果元素类型允许,则任何大小的数组都将实现以下 traits:
Copy
Clone
Debug
IntoIterator
(为[T; N]
、&[T; N]
和&mut [T; N]
实现)PartialEq
,PartialOrd
,Eq
,Ord
Hash
AsRef
,AsMut
Borrow
,BorrowMut
如果元素类型允许,则大小为 0 到 32 (inclusive) 的数组将实现 Default
trait。
作为权宜之计,trait 实现是静态生成的,最大大小为 32。
数组强制转换为 slices ([T]
) ,因此可以在数组上调用 slice 方法。实际上,这提供了用于处理数组的大多数 API。
切片具有动态大小,并且不强制转换为数组。
您可以使用 切片模式 将元素移出数组。如果需要一个元素,请参见 mem::replace
。
Examples
let mut array: [i32; 3] = [0; 3];
array[1] = 1;
array[2] = 2;
assert_eq!([1, 2], &array[1..]);
// 该循环打印: 0 1 2
for x in array {
print!("{} ", x);
}
Run您还可以迭代数组元素的引用:
let array: [i32; 3] = [0; 3];
for x in &array { }
Run您可以使用 切片模式 将元素移出数组:
fn move_away(_: String) { /* Do interesting things. */ }
let [john, roa] = ["John".to_string(), "Roa".to_string()];
move_away(john);
move_away(roa);
RunEditions
在 Rust 1.53 之前,数组没有按值实现 IntoIterator
,因此调用 array.into_iter()
方法自动引用到 slice 迭代器。
目前,为了兼容性,Rust 的 2015 和 2018 版本中保留了旧行为,忽略了 IntoIterator
的值。
将来,2015 年和 2018 年版本的行为可能会与以后版本的行为一致。
// Rust 2015 和 2018:
let array: [i32; 3] = [0; 3];
// 这将创建一个切片迭代器,产生对每个值的引用。
for item in array.into_iter().enumerate() {
let (i, x): (usize, &i32) = item;
println!("array[{}] = {}", i, x);
}
// `array_into_iter` lint 建议进行此更改以实现未来兼容性:
for item in array.iter().enumerate() {
let (i, x): (usize, &i32) = item;
println!("array[{}] = {}", i, x);
}
// 您可以使用 `IntoIterator::into_iter` 按值显式迭代数组
for item in IntoIterator::into_iter(array).enumerate() {
let (i, x): (usize, i32) = item;
println!("array[{}] = {}", i, x);
}
Run从 2021 版开始,array.into_iter()
通常使用 IntoIterator
进行值迭代,而应该像以前的版本一样使用 iter()
进行引用迭代。
// Rust 2021:
let array: [i32; 3] = [0; 3];
// 这通过引用进行迭代:
for item in array.iter().enumerate() {
let (i, x): (usize, &i32) = item;
println!("array[{}] = {}", i, x);
}
// 这是按值迭代的:
for item in array.into_iter().enumerate() {
let (i, x): (usize, i32) = item;
println!("array[{}] = {}", i, x);
}
Run未来的语言版本可能会开始将 2015 和 2018 版的 array.into_iter()
语法与 2021 版相同。
因此,在编写使用这些旧版本的代码时仍应牢记这一更改,以防止将来出现破坏。
实现这一点最安全的方法是避免这些版本中的 into_iter
语法。
如果版本更新不是不可行/不受欢迎的,则有多种选择:
- 使用
iter
,相当于旧行为,创建引用 - 使用
IntoIterator::into_iter
,相当于 2021 年后的行为 (Rust 1.53+) - 替换
for .... in array.into_iter() {
和for ... in array {
,相当于 2021 年后的行为 (Rust 1.53+)
// Rust 2015 和 2018:
let array: [i32; 3] = [0; 3];
// 这通过引用进行迭代:
for item in array.iter() {
let x: &i32 = item;
println!("{}", x);
}
// 这是按值迭代的:
for item in IntoIterator::into_iter(array) {
let x: i32 = item;
println!("{}", x);
}
// 这是按值迭代的:
for item in array {
let x: i32 = item;
println!("{}", x);
}
// IntoIter 也可以启动一个链。
// 这是按值迭代的:
for item in IntoIterator::into_iter(array).enumerate() {
let (i, x): (usize, i32) = item;
println!("array[{}] = {}", i, x);
}
RunImplementations
返回大小与 self
相同的数组,并将函数 f
按顺序应用于每个元素。
如果您不一定需要新的固定大小的数组,请考虑改用 Iterator::map
。
关于性能和栈使用的注意事项
不幸的是,这种方法的使用目前并不总是像它们可能的那样优化。 这主要涉及大数组,因为小数组上的映射似乎优化得很好。 另请注意,在调试模式下 (即 没有任何优化),这种方法可以使用大量的栈空间 (数组大小的几倍或更多)。
因此,在性能关键的代码中,尽量避免在大型数组上使用此方法或检查发出的代码。
还要尽量避免链接 maps (例如
arr.map(...).map(...)
).
在许多情况下,您可以通过在阵列上调用 .iter()
或 .into_iter()
来代替使用 Iterator::map
。
只有当您真的需要一个与结果大小相同的新数组时,才需要 [T; N]::map
Rust 的惰性迭代器往往会得到很好的优化。
Examples
let x = [1, 2, 3];
let y = x.map(|v| v + 1);
assert_eq!(y, [2, 3, 4]);
let x = [1, 2, 3];
let mut temp = 0;
let y = x.map(|v| { temp += 1; v * temp });
assert_eq!(y, [1, 4, 9]);
let x = ["Ferris", "Bueller's", "Day", "Off"];
let y = x.map(|v| v.len());
assert_eq!(y, [6, 9, 3, 3]);
Runpub fn try_map<F, R>(
self,
f: F
) -> <<R as Try>::Residual as Residual<[<R as Try>::Output; N]>>::TryType where
F: FnMut(T) -> R,
R: Try,
<R as Try>::Residual: Residual<[<R as Try>::Output; N]>,
pub fn try_map<F, R>(
self,
f: F
) -> <<R as Try>::Residual as Residual<[<R as Try>::Output; N]>>::TryType where
F: FnMut(T) -> R,
R: Try,
<R as Try>::Residual: Residual<[<R as Try>::Output; N]>,
一个容易出错的函数 f
应用于数组 self
上的每个元素,以返回与 self
或遇到的第一个错误大小相同的数组。
这个函数的返回类型取决于闭包的返回类型。
如果您从闭包返回 Result<T, E>
,您会得到一个 Result<[T; N]; E>
。
如果您从闭包中返回 Option<T>
,您会得到一个 Option<[T; N]>
.
Examples
#![feature(array_try_map)]
let a = ["1", "2", "3"];
let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
assert_eq!(b, [2, 3, 4]);
let a = ["1", "2a", "3"];
let b = a.try_map(|v| v.parse::<u32>());
assert!(b.is_err());
use std::num::NonZeroU32;
let z = [1, 2, 0, 3, 4];
assert_eq!(z.try_map(NonZeroU32::new), None);
let a = [1, 2, 3];
let b = a.try_map(NonZeroU32::new);
let c = b.map(|x| x.map(NonZeroU32::get));
assert_eq!(c, Some(a));
Run返回包含整个数组的切片。等效于 &s[..]
。
返回包含整个数组的可变切片。
等效于 &mut s[..]
。
借用每个元素,并返回一个引用数组,其大小与 self
相同。
Example
#![feature(array_methods)]
let floats = [3.1, 2.7, -1.0];
let float_refs: [&f64; 3] = floats.each_ref();
assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
Run如果与其他方法 (例如 map
) 结合使用,则此方法特别有用。
这样,如果原始数组的元素不是 Copy
,则可以避免移动原始数组。
#![feature(array_methods)]
let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
let is_ascii = strings.each_ref().map(|s| s.is_ascii());
assert_eq!(is_ascii, [true, false, true]);
// 我们仍然可以访问原始数组:它尚未移动。
assert_eq!(strings.len(), 3);
Run在一个索引处将一个数组的引用一分为二。
第一个将包含来自 [0, M)
的所有索引 (不包括索引 M
本身),第二个将包含来自 [M, N)
的所有索引 (不包括索引 N
本身)。
Panics
如果 M > N
,就会出现 panics。
Examples
#![feature(split_array)]
let v = [1, 2, 3, 4, 5, 6];
{
let (left, right) = v.split_array_ref::<0>();
assert_eq!(left, &[]);
assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
}
{
let (left, right) = v.split_array_ref::<2>();
assert_eq!(left, &[1, 2]);
assert_eq!(right, &[3, 4, 5, 6]);
}
{
let (left, right) = v.split_array_ref::<6>();
assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
assert_eq!(right, &[]);
}
Run在一个索引处将一个可变数组的引用一分为二。
第一个将包含来自 [0, M)
的所有索引 (不包括索引 M
本身),第二个将包含来自 [M, N)
的所有索引 (不包括索引 N
本身)。
Panics
如果 M > N
,就会出现 panics。
Examples
#![feature(split_array)]
let mut v = [1, 0, 3, 0, 5, 6];
let (left, right) = v.split_array_mut::<2>();
assert_eq!(left, &mut [1, 0][..]);
assert_eq!(right, &mut [3, 0, 5, 6]);
left[1] = 2;
right[1] = 4;
assert_eq!(v, [1, 2, 3, 4, 5, 6]);
Run将一个数组引用从末尾的一个索引处一分为二。
第一个将包含来自 [0, N - M)
的所有索引 (不包括索引 N - M
本身),第二个将包含来自 [N - M, N)
的所有索引 (不包括索引 N
本身)。
Panics
如果 M > N
,就会出现 panics。
Examples
#![feature(split_array)]
let v = [1, 2, 3, 4, 5, 6];
{
let (left, right) = v.rsplit_array_ref::<0>();
assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
assert_eq!(right, &[]);
}
{
let (left, right) = v.rsplit_array_ref::<2>();
assert_eq!(left, &[1, 2, 3, 4]);
assert_eq!(right, &[5, 6]);
}
{
let (left, right) = v.rsplit_array_ref::<6>();
assert_eq!(left, &[]);
assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
}
Run将一个附属数组引用从末尾的一个索引处一分为二。
第一个将包含来自 [0, N - M)
的所有索引 (不包括索引 N - M
本身),第二个将包含来自 [N - M, N)
的所有索引 (不包括索引 N
本身)。
Panics
如果 M > N
,就会出现 panics。
Examples
#![feature(split_array)]
let mut v = [1, 0, 3, 0, 5, 6];
let (left, right) = v.rsplit_array_mut::<4>();
assert_eq!(left, &mut [1, 0]);
assert_eq!(right, &mut [3, 0, 5, 6][..]);
left[1] = 2;
right[1] = 4;
assert_eq!(v, [1, 2, 3, 4, 5, 6]);
RunTrait Implementations
impl<T, const LANES: usize> AsMut<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> AsMut<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> AsRef<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> AsRef<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<[T; LANES]> for Simd<T, LANES> where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
pub fn from(array: [T; N]) -> Box<[T], Global>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
pub fn from(array: [T; N]) -> Box<[T], Global>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
impl<T, const LANES: usize> From<[bool; LANES]> for Mask<T, LANES> where
T: MaskElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<[bool; LANES]> for Mask<T, LANES> where
T: MaskElement,
LaneCount<LANES>: SupportedLaneCount,
从 16 个元素的字节数组创建 IpAddr::V6
。
Examples
use std::net::{IpAddr, Ipv6Addr};
let addr = IpAddr::from([
25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
]);
assert_eq!(
IpAddr::V6(Ipv6Addr::new(
0x1918, 0x1716,
0x1514, 0x1312,
0x1110, 0x0f0e,
0x0d0c, 0x0b0a
)),
addr
);
Runimpl<T, const LANES: usize> From<Mask<T, LANES>> for [bool; LANES] where
T: MaskElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<Mask<T, LANES>> for [bool; LANES] where
T: MaskElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<Simd<T, LANES>> for [T; LANES] where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
impl<T, const LANES: usize> From<Simd<T, LANES>> for [T; LANES] where
T: SimdElement,
LaneCount<LANES>: SupportedLaneCount,
数组的哈希值与对应的 X 像素的哈希值相同,符合实现的要求。
#![feature(build_hasher_simple_hash_one)]
use std::hash::BuildHasher;
let b = std::collections::hash_map::RandomState::new();
let a: [u8; 3] = [0xa8, 0x3c, 0x09];
let s: &[u8] = &[0xa8, 0x3c, 0x09];
assert_eq!(b.hash_one(a), b.hash_one(s));
Run如果存在,则此方法返回 self
和 other
值之间的顺序。 Read more
搜索等于数组中任何 char
的字符。
Examples
assert_eq!("Hello world".find(['l', 'l']), Some(2));
assert_eq!("Hello world".find(['l', 'l']), Some(2));
Run检查模式是否与 haystack 中的任何位置匹配
检查模式是否在 haystack 的前面匹配
如果匹配,则从 haystack 的正面删除模式。
pub fn is_suffix_of(self, haystack: &'a str) -> bool where
CharArraySearcher<'a, N>: ReverseSearcher<'a>,
pub fn is_suffix_of(self, haystack: &'a str) -> bool where
CharArraySearcher<'a, N>: ReverseSearcher<'a>,
检查模式是否与 haystack 的后面匹配
pub fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> where
CharArraySearcher<'a, N>: ReverseSearcher<'a>,
pub fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> where
CharArraySearcher<'a, N>: ReverseSearcher<'a>,
如果匹配,则从 haystack 的后面删除模式。
搜索等于数组中任何 char
的字符。
Examples
assert_eq!("Hello world".find(&['l', 'l']), Some(2));
assert_eq!("Hello world".find(&['l', 'l']), Some(2));
Run检查模式是否与 haystack 中的任何位置匹配
检查模式是否在 haystack 的前面匹配
如果匹配,则从 haystack 的正面删除模式。
pub fn is_suffix_of(self, haystack: &'a str) -> bool where
CharArrayRefSearcher<'a, 'b, N>: ReverseSearcher<'a>,
pub fn is_suffix_of(self, haystack: &'a str) -> bool where
CharArrayRefSearcher<'a, 'b, N>: ReverseSearcher<'a>,
检查模式是否与 haystack 的后面匹配
pub fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> where
CharArrayRefSearcher<'a, 'b, N>: ReverseSearcher<'a>,
pub fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> where
CharArrayRefSearcher<'a, 'b, N>: ReverseSearcher<'a>,
如果匹配,则从 haystack 的后面删除模式。
type Error = TryFromSliceError
type Error = TryFromSliceError
发生转换错误时返回的类型。
type Error = TryFromSliceError
type Error = TryFromSliceError
发生转换错误时返回的类型。
type Error = TryFromSliceError
type Error = TryFromSliceError
发生转换错误时返回的类型。
type Error = TryFromSliceError
type Error = TryFromSliceError
发生转换错误时返回的类型。
如果 Vec<T>
的大小与请求的数组的大小完全匹配,则以数组的形式获取 Vec<T>
的全部内容。
Examples
use std::convert::TryInto;
assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
assert_eq!(<Vec<i32>>::new().try_into(), Ok([]));
Run如果长度不匹配,则输入以 Err
返回:
use std::convert::TryInto;
let r: Result<[i32; 4], _> = (0..10).collect::<Vec<_>>().try_into();
assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
Run如果只需要获得 Vec<T>
的前缀就可以了,您可以先调用 .truncate(N)
。
use std::convert::TryInto;
let mut v = String::from("hello world").into_bytes();
v.sort();
v.truncate(2);
let [a, b]: [_; 2] = v.try_into().unwrap();
assert_eq!(a, b' ');
assert_eq!(b, b'd');
Run