我正在尝试练习使用策略模式,并考虑使用运行时选择的函数对向量进行排序,理想情况下能够使用可变引用更改数据。
我尝试在多个位置添加关键字
&mut
,但无法弄清楚如何让我的代码使用可变引用。
这是我的代码
use rand::Rng;
#[derive(Clone)]
pub struct Sorter<F: Fn(Vec<T>) -> Vec<T>, T: Ord + Eq + Copy> {
sort_strategy: F,
sort_data: Vec<T>,
}
impl<F: Fn(Vec<T>) -> Vec<T>, T: Ord + Eq + Copy> Sorter<F, T> {
// return self with sorted data
// how do i remove the return self and make it a mutable reference to self
pub fn sort(mut self) -> Self {
self.sort_data = (self.sort_strategy)(self.sort_data);
self
}
pub fn new(sort_strategy: F, sort_data: Vec<T>) -> Sorter<F, T> {
Sorter {
sort_strategy,
sort_data,
}
}
}
// bubble sort function
pub fn bubble_sort<T: Eq + PartialOrd + Copy>(input_vector: Vec<T>) -> Vec<T> {
let mut output_vector = input_vector.clone();
for _ in 0..output_vector.len() {
for j in 0..(output_vector.len() - 1) {
if output_vector[j] > output_vector[j + 1] {
output_vector.swap(j + 1, j);
}
}
}
output_vector
}
// quick sort function
pub fn quick_sort<T: Eq + PartialOrd + Copy>(input_vector: Vec<T>) -> Vec<T> {
if input_vector.len() <= 1 {
return input_vector;
}
let pivot = rand::thread_rng().gen_range(0..input_vector.len());
let pivot_val = input_vector[pivot];
let mut little_vector: Vec<T> = Vec::new();
let mut big_vector: Vec<T> = Vec::new();
for i in input_vector.iter().enumerate() {
if i.0 == pivot {
continue;
}
if *(i.1) > pivot_val {
big_vector.push(*(i.1));
continue;
}
if *(i.1) <= pivot_val {
little_vector.push(*(i.1))
}
}
little_vector = quick_sort(little_vector);
little_vector.push(pivot_val);
quick_sort(big_vector)
.iter()
.for_each(|n| little_vector.push(*n));
little_vector
}
#[cfg(test)]
mod tests {
use std::vec;
use super::*;
#[test]
// test that bubble_sort is functional
fn test_bubble_sort() {
let data = vec![5, 4, 3, 2, 1];
let result = bubble_sort(data);
assert_eq!(result, vec![1, 2, 3, 4, 5])
}
#[test]
// test that quick_sort is functional
fn test_quick_sort() {
let data = vec![5, 4, 3, 2, 1];
let result = quick_sort(data);
assert_eq!(result, vec![1, 2, 3, 4, 5])
}
#[test]
// test that bubble_sort works in struct Sorter
fn test_stratergy_pattern_bubble() {
let sorter = Sorter::new(bubble_sort, vec![5, 4, 3, 2, 1]);
let sorter = sorter.sort();
assert_eq!(sorter.sort_data, vec![1, 2, 3, 4, 5]);
}
#[test]
// test that quick_sort works in struct Sorter
fn test_stratergy_pattern_quick() {
let sorter = Sorter::new(quick_sort, vec![5, 4, 3, 2, 1]);
let sorter = sorter.sort();
assert_eq!(sorter.sort_data, vec![1, 2, 3, 4, 5]);
}
}
或者 在 Rust 游乐场上
我想你会希望
Sorter::sort()
看起来像这样:
pub fn sort(&mut self) {
self.sort_data = (self.sort_strategy)(self.sort_data);
}
...但是抱怨无法脱离参考。原因是您无法获取一个值并将其move到
self.sort_strategy
中。这会使 self.sort_data
处于未定义状态,虽然 Rust 有时允许这种部分移动的对象,但分配给 self.sort_data
与此不兼容。
如果你不想改变
sort_data
的签名,那么最简单的方法就是用空向量替换self.sort_data
,即使用std::mem::replace(&mut self.sort_data, vec![])
。对于实现 Default
的类型,例如 Vec
,有一个 std::mem::take()
函数可以替换默认值。然后 sort()
看起来像这样:
pub fn sort(&mut self) {
self.sort_data = (self.sort_strategy)(std::mem::take(&mut self.sort_data));
}
对测试套件进行细微更改后不捕获
sort
的结果,您的测试通过了。 游乐场