是否可以对包含return语句的函数片段进行因子分解



在堆数据结构的实现中,我有以下代码:

pub fn has_heap_property(&self) -> bool{
for i in 0..self.array.len() {
match self.left(i) {
Some(child) => {
if self.array[i] > self.array[child]{
return false
}
}
None => {}
}
match self.right(i) {
Some(child) => {
if self.array[i] > self.array[child]{
return false
}
}
None => {}
}
}
true
}

match self.left(i)match self.right(i)下的7条线是相同的。我想重构这段代码以避免重复,但由于重复代码中的return语句,将其封装到闭包中将不允许从父函数返回。有没有办法重构它?

我的尝试如下,但没有编译:

pub fn has_heap_property(&self) -> bool{
for i in 0..self.array.len() {
let check_child = |maybe_child: Option<usize>, usize|{
match maybe_child {
Some(child) => {
if self.array[i] > self.array[child]{
return false;
}
}
None => {}
}
};
check_child(self.left(i)); 
check_child(self.right(i)); 
}
true
}

完整代码:

/// This module defines the heap data structure
use std::fmt::Debug;
#[derive(Debug)]
struct MaxHeap<T> {
array: Vec<T>,
heapsize: usize,
}
impl<T> MaxHeap<T>
where T: std::cmp::Ord + Copy + Debug {
fn left(&self, idx: usize) -> Option<usize> {
let result = idx * 2 + 1;
if result < self.heapsize {
Some(result)
} else {
None
}
}
fn right(&self, idx: usize) -> Option<usize> {
let result = idx * 2 + 2;
if result < self.heapsize {
Some(result)
} else {
None
}
}
fn parent(idx: usize) -> Option<usize> {
if idx > 0 {
Some((idx - 1) / 2)
} else {
None
}
}
pub fn max_heapify(&mut self, idx: usize) {
let mut options = vec![];
let mut maybe_option = |maybe_child: Option<usize>| {
match maybe_child {
Some(child_idx) => {
options.push((&self.array[child_idx], child_idx))
}
None => {}
}
};
maybe_option(self.left(idx));
maybe_option(self.right(idx));
let swap_with = options.iter().fold((&self.array[idx], idx), |a, &b| a.max(b)).1;
if swap_with == idx {
return;
} else {
self.array.swap(idx, swap_with);
self.max_heapify(swap_with);
}
}
pub fn build_heap(array: Vec<T>) -> MaxHeap<T> {
let mut mh = MaxHeap { heapsize: array.len(), array };
for idx in (0..mh.heapsize / 2).rev() {
mh.max_heapify(idx);
}
mh
}
pub fn has_heap_property(&self) -> bool {
for i in 0..self.heapsize {
match self.left(i) {
Some(child) => {
if self.array[i] < self.array[child] {
return false;
}
}
None => {}
}
match self.right(i) {
Some(child) => {
if self.array[i] < self.array[child] {
return false;
}
}
None => {}
}
}
true
}
fn heapsort(&mut self) {
while self.heapsize > 0 {
self.array.swap(0, self.heapsize - 1);
self.heapsize -= 1;
self.max_heapify(0)
}
}
fn return_array(self) -> Vec<T> {
self.array
}
}
pub fn heapsort<T>(array: &[T]) -> Vec<T>
where T: std::cmp::Ord + Copy + Debug {
let mut mh = MaxHeap::build_heap(Vec::from(array));
mh.heapsort();
mh.return_array()
}
fn main() {
let mut mh = MaxHeap { array: vec![30, 100, 200, 10, 20, 30], heapsize: 6};
println!("Incorrect maxheap {:?} has max-heap property: {:?}", mh, mh.has_heap_property());
let mut mh = MaxHeap::build_heap(vec![30, 100, 200, 10, 20, 30]);
println!("Correct maxheap {:?} has max-heap property: {:?}", mh, mh.has_heap_property());
}

不能将包含类似return语句的代码重构为闭包,因为它引用了当前范围。

我会这样重构它:

pub fn has_heap_property(&self) -> bool {
(0..self.array.len()).all(|i| match (self.left(i), self.right(i)) {
(Some(child), _) | (_, Some(child)) if self.array[i] < self.array[child] => false,
_ => true,
})
}

最新更新