/// ```
/// ptr len capacity
/// +--------+--------+--------+
/// | 0x0123 | 2 | 4 |
/// +--------+--------+--------+
/// |
/// v
/// Heap +--------+--------+--------+--------+
/// | 'a' | 'b' | uninit | uninit |
/// +--------+--------+--------+--------+
/// ```
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 01.返回一个指向切片缓冲区的原始指针。
let _as_ptr = vector.as_ptr(); // *const T
// 02.返回一个指向切片缓冲区的不安全可变指针。
let _as_mut_ptr = vector.as_mut_ptr(); // *mut T
// 03.返回跨越切片的两个原始指针。
// 返回的范围是半开的,这意味着结束指针指向切片的最后一个元素。 这样,一个空切片就由两个相等的指针表示,两个指针之间的差值表示切片的大小。
// 有关使用这些指针的警告,请参阅 as_ptr。 结束指针需要格外小心,因为它不指向切片中的有效元素。
// 此函数对于与使用两个指针来引用内存中一系列元素的外部接口进行交互非常有用,这在 C++ 中很常见。
// 检查指向元素的指针是否指向此切片的元素也很有用:
let _as_ptr_range = vector.as_ptr_range(); // Range<*const T>
// 04.返回跨越切片的两个不安全的可变指针。
// 返回的范围是半开的,这意味着结束指针指向切片的最后一个元素。 这样,一个空切片就由两个相等的指针表示,两个指针之间的差值表示切片的大小。
// 有关使用这些指针的警告,请参阅 as_mut_ptr。 结束指针需要格外小心,因为它不指向切片中的有效元素。
// 此函数对于与使用两个指针来引用内存中一系列元素的外部接口进行交互非常有用,这在 C++ 中很常见。
let _as_mut_ptr_range = vector.as_mut_ptr_range(); // Range<*mut T>
// 05.根据索引类型返回对元素或子切片的引用。
let _get_single = vector.get(1); // Option<&<I as SliceIndex<[T]>>::Output>
println!("{:?}", _get_single); // Some(1)
let _get_range = vector.get(1..); // 入参是一个范围
println!("{:?}", _get_range); // Some([1, 2, 3, 4, 5, 6, 7, 8, 9])
// 06.返回对元素或子切片的可变引用,具体取决于索引的类型(请参阅 get)或 None 如果索引超出范围。
let _get_mut = vector.get_mut(1); // 入参单个索引
println!("{:?}", _get_mut); // Some(1)
// 这里和上面的变量名称相同,因为可变的引用只能存在一个
let _get_mut = vector.get_mut(1..); // 入参是一个范围、return Option<&mut I::Output>
println!("{:?}", _get_mut); // Some([1, 2, 3, 4, 5, 6, 7, 8, 9])
// 07.返回对元素或子切片的引用,而不进行边界检查。有关安全的替代方案,请参阅 get。
unsafe {
let _get_unchecked = vector.get_unchecked(1); // &<I as SliceIndex<[T]>>::Output
println!("{:?}", _get_unchecked); // 1
}
// 08.返回对元素或子切片的可变引用,而不进行边界检查。有关安全的替代方案,请参阅 get_mut。
unsafe {
let _get_unchecked_mut = vector.get_unchecked_mut(1); // &mut I::Output
println!("{:?}", _get_unchecked_mut); // 1
}
// 09.交换切片中的两个元素。
vector.swap(1, 2); // 无返回值
println!("a: {:?}, b: {:?}", vector.get(1).unwrap(), vector.get(2).unwrap()); // a: 2, b: 1
// 10.原地反转切片中元素的顺序。
vector.reverse();
println!("{:?}", vector); //[9,8,7,6,5,4,3,1,2,0]
// 11.返回切片上的迭代器。
let _iter = vector.iter(); // Iter<'_, T>
// 12.返回一个允许修改每个值的迭代器。
let _iter_mut = vector.iter_mut(); // IterMut<'_, T>
// 13.在所有长度大小的连续窗口上返回一个迭代器。窗户重叠。如果切片比 size 短,则迭代器不返回任何值。
let mut _windows = vector.windows(2); // Windows<'_, T>
println!("{:?}", _windows.next()); // Some([9, 8])
println!("{:?}", _windows.next()); // Some([8, 7])
println!("{:?}", _windows.next()); // Some([7, 6])
// 01.检查此切片中的所有字节是否都在 ASCII 范围内。
let vec_u8: Vec<u8> = Vec::from("Hello World");
let is_ascii: bool = vec_u8.is_ascii(); // true
println!("{:?} is ascii: {:?}", String::from_utf8_lossy(&vec_u8), is_ascii); // "Hello World" is ascii: true
// 02.检查两个切片是否是不区分大小写的 ASCII 匹配。
let vec_u8_01: Vec<u8> = Vec::from("Hello World");
let vec_u8_02: Vec<u8> = Vec::from("HELLO WORLD");
let eq_ignore_ascii_case = vec_u8_01.eq_ignore_ascii_case(&vec_u8_02); // true
println!("{} and {} is equal ignore ascii case: {}",
String::from_utf8(vec_u8_01).unwrap(), // move 语意
String::from_utf8(vec_u8_02).unwrap(), // move 语意
eq_ignore_ascii_case);
let mut vec_u8: Vec<u8> = Vec::from("Hello World"); // "[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
// 03.将此切片就地转换为其 ASCII 小写等效。非 ASCII 字母不变。
vec_u8.make_ascii_lowercase(); // [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
// 04.将此切片就地转换为其 ASCII 大写等效。非 ASCII 字母不变。
vec_u8.make_ascii_uppercase(); // [72, 69, 76, 76, 79, 32, 87, 79, 82, 76, 68]
let vec_u8 = Vec::from("Hello World");
// 05.返回一个包含此切片副本的向量,其中每个字节都映射到其 ASCII 大写等效项。
let a: Vec<u8> = vec_u8.to_ascii_uppercase(); // copy 语意
// 06.返回一个包含此切片副本的向量,其中每个字节都映射到其 ASCII 小写等效项。
let b: Vec<u8> = vec_u8.to_ascii_lowercase(); // copy 语意
println!("a is {:?},\nb is {:?}", a, b);
// 07.对切片进行排序。
// 这种排序是稳定的(即,不会对相等的元素重新排序)并且 O(n * log(n)) 最坏情况。
let mut slice_u8 = [72i32, 69, 76, 76, 79, 32, 87, 79, 82, 76, 68];
slice_u8.sort();
println!("{:?}", slice_u8); // [32, 68, 69, 72, 76, 76, 76, 79, 79, 82, 87]
// 08.使用比较器函数对切片进行排序。
let mut slice_u8 = [72, 69, 76, 76, 79, 32, 87, 79, 82, 76, 68];
slice_u8.sort_by(|a, b| a.partial_cmp(b).unwrap());
println!("{:?}", slice_u8); // [32, 68, 69, 72, 76, 76, 76, 79, 79, 82, 87]
// 09.使用 key 提取功能对切片进行排序。
let mut slice_u8 = [-72i32, 69, -76, 76, 79, 32, 87, 79, 82, 76, 68];
// 10.使用 key 提取功能对切片进行排序。在排序过程中,每个元素只调用一次 key 函数。
let mut slice_u8 = [-72i32, 69, -76, 76, 79, 32, 87, 79, 82, 76, 68];
slice_u8.sort_by_cached_key(|k| k.to_string());
println!("{:?}", slice_u8); // [-72, -76, 32, 68, 69, 76, 76, 79, 79, 82, 87]
// 11.将 self 复制到新的 Vec 中。
let vec_u8 = Vec::from("Hello World");
let vec_copy = vec_u8.to_vec();
assert_eq!(vec_u8, vec_copy); // true
// 12.在不进行克隆和内存分配情况下,转换 self 到一个 vector。
// 可以通过 Vec<T> 的 into_boxed_slice 方法将结果 vector 转换回 box。
let box_slice: Box<[i32; 5]> = Box::new([1, 2, 3, 4, 5]);
let into_vec = box_slice.to_vec(); // Vec<T, A>
println!("{:?}", into_vec); // [1, 2, 3, 4, 5]
// 13.通过重复切片 n 次来创建向量。
let vec_u8: Vec<u8> = Vec::from("Hello");
let repeat: Vec<u8> = vec_u8.repeat(2);
println!("{:?}", repeat); // [72, 101, 108, 108, 111, 72, 101, 108, 108, 111]
// 14.将 T 的切片展平为单个值 Self::Output。
let vec_u8: [&str; 2] = ["hello", " world"];
let concat = vec_u8.concat();
println!("{}", concat); // hello world
// 15.将 T 的切片展平为单个值 Self::Output,在每个值之间放置一个给定的分隔符。
let vec_u8: [&str; 2] = ["hello", "world"];
let vec_join = vec_u8.join(",");
println!("{}", vec_join); // hello,world
// ---- impl<T>[T] 切片常规方法 ----
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 16.返回切片中的元素数
let _len = vector.len(); // usize
// 17.如果切片的长度为0,则返回true
let _is_empty = vector.is_empty(); // bool
// 18.返回切片的第一个元素,如果为空,则返回 None 。
let _first = vector.first(); // Option<&T>
// 19.返回指向切片第一个元素的可变指针,如果为空,则返回 None 。
let _first_mut = vector.first_mut(); // Option<&mut T>
// 20.返回切片的最后一个元素,如果为空则返回 None。
let _last = vector.last(); // Option<&T>
// 21.返回指向切片中最后一项的可变指针。
let _last_mut = vector.last_mut(); // Option<&mut T>
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 22.返回切片的第一个和所有其余元素,如果为空,则返回 None 。
let _split_first = vector.split_first(); // Option<(&T, &[T])>
println!("{:?}", _split_first); // Some((0, "[1, 2, 3, 4, 5, 6, 7, 8, 9]))
// 22.返回切片的第一个和所有其余元素,如果为空,则返回 None 。
let _split_first_mut = vector.split_first_mut(); // Option<(&mut T, &mut [T])>
println!("{:?}", _split_first_mut); // Some((0, "[1, 2, 3, 4, 5, 6, 7, 8, 9]))
// 23.返回切片的最后一个和所有其余元素,如果为空,则返回 None 。
let _split_last = vector.split_last(); // Option<(&T, &[T])>
println!("{:?}", _split_last); // Some((9, "[0, 1, 2, 3, 4, 5, 6, 7, 8]))
// 23.返回切片的最后一个和所有其余元素,如果为空,则返回 None 。
let _split_last_mut = vector.split_last_mut(); // Option<(&mut T, &mut [T])>
println!("{:?}", _split_last_mut); // Some((9, "[0, 1, 2, 3, 4, 5, 6, 7, 8]))
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 24.从切片的开头开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是切片,并且不重叠。 如果 chunk_size 不划分切片的长度,那么最后一个 chunk 的长度不会是 chunk_size。
// 请参阅 chunks_exact 以获取此迭代器的变体,该变体返回始终完全是 chunk_size 元素的块,以及相同迭代器但从切片末尾开始的 rchunks。
let mut _chunks = vector.chunks(2); // Chunks<'_, T>
println!("{:?}", _chunks); // Chunks { v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size: 2 }
println!("{:?}", _chunks.next()); // Some([9, 8])
println!("{:?}", _chunks.next()); // Some([7, 6])
// 25.从切片的开头开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是可变切片,不重叠。如果 chunk_size 不划分切片的长度,那么最后一个 chunk 的长度不会是 chunk_size。
// 请参阅 chunks_exact_mut 以获取此迭代器的变体,该变体返回始终完全是 chunk_size 元素的块,以及 rchunks_mut 用于相同迭代器但从切片末尾开始。
let mut _chunks_mut = vector.chunks_mut(4); // ChunksMut<'_, T>
println!("{:?}", _chunks_mut); // ChunksMut { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size: 2 }
println!("{:?}", _chunks_mut.next()); // Some([9, 8, 7, 6])
println!("{:?}", _chunks_mut.next()); // Some([5, 4, 3, 2])
println!("{:?}", _chunks_mut.next()); // Some([1, 0])
// 26.从切片的开头开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是切片并且不重叠。 如果 chunk_size 没有划分切片的长度,那么最后到 chunk_size-1 的元素将被省略,并且可以从迭代器的剩余函数中检索。
// 由于每个块都有确切的 chunk_size 元素,编译器通常可以比在`chunks`的情况下更好地优化结果代码。
// 请参阅`chunks`以了解此迭代器的变体,该变体也将余数作为较小的块返回,而 rchunks_exact 则用于相同的迭代器,但从切片的末尾开始。
let mut _chunks_exact = vector.chunks_exact(4); // ChunksExact<'_, T>
println!("{:?}", _chunks_exact); // ChunksExact { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], rem: [], chunk_size: 5 }
println!("{:?}", _chunks_exact.next()); // Some([9, 8, 7, 6])
println!("{:?}", _chunks_exact.next()); // Some([5, 4, 3, 2])
println!("{:?}", _chunks_exact.next()); // None
// 27.从切片的开头开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是可变切片,不重叠。如果 chunk_size 不划分切片的长度,则最后到 chunk_size-1 的元素将被省略,并且可以从迭代器的 into_remainder 函数中检索。
// 由于每个块都有确切的 chunk_size 元素,编译器通常可以比在 chunks_mut 的情况下更好地优化结果代码。
// 有关此迭代器的变体,请参阅 chunks_mut,该变体也将余数作为较小的块返回,而 rchunks_exact_mut 则用于相同的迭代器,但从切片的末尾开始。
let mut _chunks_exact_mut = vector.chunks_exact_mut(4); // ChunksExactMut<'_, T>
println!("{:?}", _chunks_exact_mut); // ChunksExactMut { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], rem: [], chunk_size: 5 }
println!("{:?}", _chunks_exact_mut.next()); // Some([9, 8, 7, 6])
println!("{:?}", _chunks_exact_mut.next()); // Some([5, 4, 3, 2])
println!("{:?}", _chunks_exact_mut.next()); // None
let vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 28.从切片的末尾开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是切片并且不重叠。如果 chunk_size 不划分切片的长度,那么最后一个 chunk 的长度不会是 chunk_size。
// 有关此迭代器的变体,请参阅 rchunks_exact,该变体返回始终恰好为 chunk_size 元素的块,以及相同迭代器但从切片开头开始的`chunks`。
let mut _rchunks = vector.rchunks(3); // RChunks<'_, T>
println!("{:?}", _rchunks); // RChunks { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size: 3 }
println!("{:?}", _rchunks.next()); // Some([7, 8, 9])
println!("{:?}", _rchunks.next()); // Some([4, 5, 6])
// 29.从切片的末尾开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是可变切片,不重叠。 如果 chunk_size不划分切片的长度,那么最后一个 chunk 的长度不会是 chunk_size。
// 请参阅 rchunks_exact_mut 以获取此迭代器的变体,该变体返回始终完全是 chunk_size 元素的块,而 chunks_mut 则返回相同迭代器但从切片的开头开始。
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut _rchunks_mut = vector.rchunks_mut(4); // RChunksMut<'_, T>
println!("{:?}", _rchunks_mut); // RChunksMut { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size: 3 }
println!("{:?}", _rchunks_mut.next()); // Some([6, 7, 8, 9])
println!("{:?}", _rchunks_mut.next()); // Some([2, 3, 4, 5])
println!("{:?}", _rchunks_mut.next()); // Some([0, 1])
// 30.从切片的末尾开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是切片并且不重叠。如果 chunk_size 没有划分切片的长度,那么最后到 chunk_size-1 的元素将被省略,并且可以从迭代器的剩余函数中检索。
let mut _rchunks_exact = vector.rchunks_exact(4); // RChunksExact<'_, T>
println!("{:?}", _rchunks_exact); // RChunksExact { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], rem: [], chunk_size: 2 }
println!("{:?}", _rchunks_exact.next()); // Some([6, 7, 8, 9])
println!("{:?}", _rchunks_exact.next()); // Some([2, 3, 4, 5])
println!("{:?}", _rchunks_exact.next()); // None
// 31.从切片的末尾开始,一次返回切片的 chunk_size 元素上的迭代器。
// 块是可变切片,不重叠。 如果 chunk_size 没有划分切片的长度,则最后到 chunk_size-1 的元素将被省略,并且可以从迭代器的 into_remainder 函数中检索。
// 由于每个块都有确切的 chunk_size 元素,编译器通常可以比在 chunks_mut 的情况下更好地优化结果代码。
// 请参阅 rchunks_mut 以获取此迭代器的变体,该变体也将余数作为较小的块返回,而 chunks_exact_mut 则用于相同的迭代器,但从切片的开头开始。
let mut _rchunks_exact_mut = vector.rchunks_exact_mut(4); // RChunksExactMut<'_, T>
println!("{:?}", _rchunks_exact_mut); // RChunksExactMut { v: [2, 3, 4, 5, 6, 7, 8, 9], rem: [0, 1], chunk_size: 4 }
println!("{:?}", _rchunks_exact_mut.next()); // Some([6, 7, 8, 9])
println!("{:?}", _rchunks_exact_mut.next()); // Some([2, 3, 4, 5])
println!("{:?}", _rchunks_exact_mut.next()); // None
// 32.在一个索引处将一个切片一分为二。
// 第一个将包含来自 [0,mid) 的所有索引(不包括索引 mid 本身),第二个将包含来自 [mid,len) 的所有索引(不包括索引 len 本身)。
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut _split_at = vector.split_at(2); // (&[T], &[T])
println!("{:?}", _split_at); // ([0,1], [2,3,4,5,6,7,8,9])
// 33.在一个索引处将一个可变切片一分为二。
// 第一个将包含来自 [0, mid) 的所有索引(不包括索引 mid 本身),第二个将包含来自 [mid, len) 的所有索引(不包括索引 len 本身)。
let mut _split_at_mut = vector.split_at_mut(2); // (&mut [T], &mut [T])
println!("{:?}", _split_at_mut); // ([0,1], [2,3,4,5,6,7,8,9])
// 34.返回由匹配 pred 的元素分隔的子切片上的迭代器。匹配的元素不包含在子切片中。
// 如果第一个元素匹配,一个空切片将是迭代器返回的第一个项目。类似地,如果切片中的最后一个元素匹配,则迭代器返回的最后一项将是一个空切片:
// 如果两个匹配的元素直接相邻,它们之间将出现一个空切片:
let mut _split = vector.split(|&x| x % 3 == 0); // Split<'_, T, F>
println!("{:?}", _split); //Split { v: [0,1,2,3,4,5,6,7,8,9], finished: false }
// 35.返回由匹配 pred 的元素分隔的可变子切片上的迭代器。匹配的元素不包含在子切片中。
let mut _split_mut = vector.split_mut(|&x| x % 3 == 0); // SplitMut<'_, T, F>
println!("{:?}", _split_mut); //SplitMut { v: [0,1,2,3,4,5,6,7,8,9], finished: false }
// 36.返回由匹配 pred 的元素分隔的子切片上的迭代器。匹配的元素作为终止符包含在前一个子切片的末尾。
// 如果切片的最后一个元素匹配,则该元素将被视为前一个切片的终止符。该切片将是迭代器返回的最后一项。
let mut _split_inclusive = vector.split_inclusive(|&x| x % 3 == 0); // SplitInclusive<'_, T, F>
println!("{:?}", _split_inclusive); // SplitInclusive { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], finished: false }
// 37.返回由匹配 pred 的元素分隔的可变子切片上的迭代器。匹配的元素作为终止符包含在前一个子切片中。
let mut _split_inclusive_mut = vector.split_inclusive_mut(|&x| x % 1 == 0);
println!("{:?}", _split_inclusive_mut); // SplitInclusiveMut { v: [0,1,2,3,4,5,6,7,8,9], finished: false }
// 38.返回由匹配 pred 的元素分隔的子切片的迭代器,从切片的末尾开始并向后工作。匹配的元素不包含在子切片中。
// 与 split() 一样,如果第一个或最后一个元素匹配,一个空切片将是迭代器返回的第一个(或最后一个)项目。
let mut _rsplit = vector.rsplit(|&x| x % 3 == 0);
println!("{:?}", _rsplit); // RSplit { v: [0,1,2,3,4,5,6,7,8,9], finished: false }
// 39.在由匹配 pred 的元素分隔的子切片上返回迭代器,仅限于返回最多 n 个项目。匹配的元素不包含在子切片中。
// 返回的最后一个元素(如果有)将包含切片的其余部分。
let mut _rsplit_mut = vector.rsplit_mut(|&x| x % 3 == 0);
println!("{:?}", _rsplit_mut); // RSplitMut { v: [0,1,2,3,4,5,6,7,8,9], finished: false }
// 40.返回由匹配 pred 的元素分隔的子切片上的迭代器,仅限于返回最多 n 个项目。 这从切片的末尾开始并向后工作。 匹配的元素不包含在子切片中。
// 返回的最后一个元素(如果有)将包含切片的其余部分。
let mut _rsplitn = vector.rsplitn(2, |&x| x % 3 == 2);
println!("{:?}", _rsplitn); // RSplitN { inner: GenericSplitN { iter: RSplit { v: "[0,1,2,3,4,5,6,7,8,9], finished: false }, count: 2 } }
// 41.返回由匹配 pred 的元素分隔的子切片上的迭代器,仅限于返回最多 n 个项目。 这从切片的末尾开始并向后工作。 匹配的元素不包含在子切片中。
// 返回的最后一个元素(如果有)将包含切片的其余部分。
let mut _rsplitn_mut = vector.rsplitn_mut(3, |&x| x % 2 == 0);
println!("{:?}", _rsplitn_mut); // RSplitNMut { inner: GenericSplitN { iter: RSplitMut { v: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], finished: false }, count: 3 } }
// 42.如果切片包含具有给定值的元素,则返回 true。
let _contains = vector.contains(&2);
// 43.如果 needle 是切片的前缀,则返回true。
let _starts_with = vector.starts_with(&[0, 1]);
// 44.如果 needle 是切片的后缀,则返回true。
let _ends_with = vector.ends_with(&[9]);
// 45.返回删除前缀的子切片。如果切片不以前缀开头,则返回 None。
let _strip_prefix = vector.strip_prefix(&[1, 2, 3]); // Option<&[T]>
// 46.返回删除后缀的子切片。如果切片不以后缀结尾,则返回 None。
let _strip_suffix = vector.strip_suffix(&[8, 9]); // Option<&[T]>
// 47. 二分搜索在此排序切片中搜索给定元素。
// 如果找到该值,则返回 Result::Ok,其中包含匹配元素的索引。 如果有多个匹配项,则可以返回任何匹配项。
// 该索引是确定性选择的,但在 Rust 的未来版本中可能会发生变化。
// 如果未找到该值,则返回 Result::Err,其中包含可以在保持排序顺序的同时插入匹配元素的索引。
// 另请参见 binary_search_by、binary_search_by_key 和 partition_point。
let _binary_search = vector.binary_search(&3); // Result<usize, usize>
println!("{:?}", _binary_search); // Ok(3)
// 48.使用比较器函数二分搜索这个排序的切片。
// 比较器函数应实现与底层切片的排序顺序一致的顺序,返回一个顺序代码,指示其参数是小于、等于还是大于所需目标。
// 如果找到该值,则返回 Result::Ok,其中包含匹配元素的索引。 如果有多个匹配项,则可以返回任何匹配项。
// 该索引是确定性选择的,但在 Rust 的未来版本中可能会发生变化。
// 如果未找到该值,则返回 Result::Err,其中包含可以在保持排序顺序的同时插入匹配元素的索引。
// 另请参见 binary_search、binary_search_by_key 和 partition_point。
let seek = 5;
let mut _binary_search_by = vector.binary_search_by(|probe| probe.cmp(&seek));
println!("{:?}", _binary_search_by); //Ok(5)
// 49. 使用键提取功能二进制搜索这个排序的切片。
// 假设切片按键排序,例如 sort_by_key 使用相同的键提取函数。
// 如果找到该值,则返回 Result::Ok,其中包含匹配元素的索引。 如果有多个匹配项,则可以返回任何匹配项。
// 该索引是确定性选择的,但在 Rust 的未来版本中可能会发生变化。
// 如果未找到该值,则返回 Result::Err,其中包含可以在保持排序顺序的同时插入匹配元素的索引。
// 另请参见 binary_search、binary_search_by 和 partition_point。
let _binary_search_by_key = vector.binary_search_by_key(&1, |&a| a);
println!("{:?}", _binary_search_by_key); //Ok(1)
// 50.对切片进行排序,但可能不保留相等元素的顺序。
// 这种排序是不稳定的(即可能对相等的元素重新排序)、就地(即不分配)和 O(n * log(n)) 最坏的情况。
// 当前的算法基于 Orson Peters 的模式失败快速排序,它结合了随机快速排序的快速平均情况和堆排序的快速最坏情况,同时在具有某些模式的切片上实现了线性时间。
// 它使用一些随机化来避免退化情况,但使用固定的种子来始终提供确定性的行为。
// 它通常比稳定排序更快,除非在一些特殊情况下,例如,当切片由几个串联的排序序列组成时。
vector.sort_unstable();
// 51.使用比较器函数对切片进行排序,但可能不保留相等元素的顺序。
// 这种排序是不稳定的(即可能对相等的元素重新排序)、就地(即不分配)和 O(n * log(n)) 最坏的情况。
// 比较器函数必须为切片中的元素定义总排序。 如果排序不是全部,则元素的顺序是未指定的。 一个订单是一个总订单,如果它是(对于所有 a、b 和 c):
// 完全和反对称:恰好 a < b、a == b 或 a > b 之一为真,并且
// 传递,a < b 和 b < c 意味着 a < c。 == 和 > 也必须如此。
// 例如,虽然 f64 没有实现 Ord 因为 NaN != NaN,但当我们知道切片不包含 NaN 时,我们可以使用 partial_cmp 作为我们的排序函数。
let _sort_unstable_by = vector.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
// 52.使用键提取函数对切片进行排序,但可能不保留相等元素的顺序。
// 这种排序是不稳定的(即可能对相等的元素重新排序)、就地(即不分配)和 O(m * n * log(n)) 最坏的情况,其中关键函数是 O(m)。
let _sort_unstable_by_key = vector.sort_unstable_by_key(|k| k.abs());
// 53.重新排序切片,使索引处的元素位于其最终排序位置。
// 这种重新排序具有附加属性,即位置 i < index 处的任何值都将小于或等于位置 j > index 处的任何值。
// 此外,这种重新排序是不稳定的(即任何数量的相等元素可能会在位置索引处结束)、就地(即不分配)和 O(n) 最坏情况。
// 此函数在其他库中也称为/称为“第 k 个元素”。 它返回以下值的三元组:所有小于给定索引处的元素、给定索引处的值以及所有大于给定索引处的元素。
// 当前算法基于用于 sort_unstable 的相同快速排序算法的快速选择部分。
let _select_nth_unstable = vector.select_nth_unstable(3); // (&mut [T], &mut T, &mut [T])
println!("{:?}", _select_nth_unstable); //([0, 1, 2], 3, [4, 5, 6, 7, 8, 9])
// 54.使用比较器函数对切片重新排序,以便索引处的元素位于其最终排序位置。
// 此重新排序具有附加属性,即使用比较器函数,位置 i < index 处的任何值将小于或等于位置 j > index 处的任何值。
// 此外,这种重新排序是不稳定的(即任何数量的相等元素可能会在位置索引处结束)、就地(即不分配)和 O(n) 最坏情况。
// 此函数在其他库中也称为“第 k 个元素”。 它使用提供的比较器函数返回以下值的三元组:小于给定索引处的所有元素、给定索引处的值以及大于给定索引处的所有元素。
let _select_nth_unstable_by = vector.select_nth_unstable_by(3, |a, b| b.cmp(a));
println!("{:?}", _select_nth_unstable_by); //([9,8,7], 6, [5,4,3,2,1,0])
// 55.使用键提取函数对切片重新排序,以便索引处的元素位于其最终排序位置。
// 此重新排序具有附加属性,即使用键提取函数,位置 i < index 处的任何值将小于或等于位置 j > index 处的任何值。
// 此外,这种重新排序是不稳定的(即任何数量的相等元素可能会在位置索引处结束)、就地(即不分配)和 O(n) 最坏情况。
// 此函数在其他库中也称为“第 k 个元素”。 它使用提供的键提取函数返回以下值的三元组:小于给定索引处的所有元素、给定索引处的值以及大于给定索引处的所有元素。
let _select_nth_unstable_by_key = vector.select_nth_unstable_by_key(3, |a| a.abs());
println!("{:?}", _select_nth_unstable_by_key); //([0,1,2], 3, [4,5,6,7,8,9])
let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 55.原地旋转切片,使切片的第一个 mid 元素移动到末尾,而最后一个 self.len() - mid 元素移动到前面。 调用rotate_left后,之前索引mid的元素将成为切片中的第一个元素。
vector.rotate_left(2);
println!("{:?}", vector); // [2,3,4,5,6,7,8,9,0,1]
// 56.通过克隆值用元素填充 self 。
vector.fill(100);
println!("{:?}", vector); // [100,100,100,100,100,100,100,100,100,100]
//57.用通过重复调用闭包返回的元素填充 self 。
// 此方法使用闭包来创建新值。 如果您希望克隆给定值,请使用填充。 如果你想使用 Default trait 来生成值,你可以传递 Default::default 作为参数。
vector.fill_with(Default::default);
println!("{:?}", vector); // [0,0,0,0,0,0,0,0,0,0]
// 58.将元素从 src 复制到 self.
// src 的长度必须与 self 相同。
// 如果 T 实现了 Copy,则使用 copy_from_slice 可以提高性能。
vector.clone_from_slice(&[1,2,3,3,4,5,4,3,2,1]);
println!("{:?}", vector); // [1,2,3,3,4,5,4,3,2,1]
// 59.使用 memcpy 将所有元素从 src 复制到 self 中。
// src 的长度必须与 self 相同。
// 如果 T 没有实现 Copy,则使用 clone_from_slice。
vector.copy_from_slice(&[1,2,3,3,4,5,6,7,8,9]);
println!("{:?}", vector); // [1,2,3,3,4,5,6,7,8,9]
// 60.使用 memmove 将元素从切片的一部分复制到其自身的另一部分。
// src 是 self 内要复制的范围。 dest 是 self 内要复制到的范围的起始索引,其长度与 src 相同。
// 这两个范围可能重叠。 两个范围的结尾必须小于或等于 self.len()。
vector.copy_within(1..7, 4);
println!("{:?}", vector); // [1,2,3,3,2,3,3,4,5,6]
// 61.将 self 中的所有元素与 other 中的元素交换。
// other 的长度必须与 self 相同。
let mut slice1 = [0, 0];
let mut slice2 = [1, 2, 3, 4];
slice1.swap_with_slice(&mut slice2[2..]);
println!("{:?}", slice1); // [3,4]
// -------------------------------------------------------------
// 62.将切片转换为另一种类型的切片,确保保持类型的对齐。
// 此方法将切片分成三个不同的切片:前缀、正确对齐的新类型中间切片和后缀切片。
// 该方法可能使中间切片成为给定类型和输入切片的最大长度,但只有您的算法的性能应该取决于它,而不是它的正确性。 允许将所有输入数据作为前缀或后缀切片返回。
// 当输入元素 T 或输出元素 U 的大小为零时,此方法没有任何用途,并且将返回原始切片而不拆分任何内容。
unsafe {
let _align_to = vector.align_to::<u16>();
}
// 63.将切片转换为另一种类型的切片,确保保持类型的对齐。
// 此方法将切片分成三个不同的切片:前缀、正确对齐的新类型中间切片和后缀切片。
// 该方法可能使中间切片成为给定类型和输入切片的最大长度,但只有您的算法的性能应该取决于它,而不是它的正确性。 允许将所有输入数据作为前缀或后缀切片返回。
// 当输入元素 T 或输出元素 U 的大小为零时,此方法没有任何用途,并且将返回原始切片而不拆分任何内容。
unsafe {
let mut _align_to_mut = vector.align_to_mut::<u16>();
}
// 64.根据给定的断言,返回分区点的索引(第二个分区的第一个元素的索引)。
let _partition_point = vector.partition_point(|&x| x < 5);
// 假定根据给定的断言对切片进行分区。 这意味着谓词返回 true 的所有元素都位于切片的开头,而谓词返回 false 的所有元素都位于切片的末尾。
// 例如,[7,15,3,5,4,12,6] 是在谓词 x % 2 != 0 下的分区(所有奇数都在开头,所有偶数都在结尾)。
// 如果此切片未分区,则返回的结果是未指定且无意义的,因为此方法执行一种二分查找。
// 另请参见 binary_search、binary_search_by 和 binary_search_by_key。