Skip to content

Commit fd5fa01

Browse files
committed
Use helper functions for min/max_idx
1 parent 3d11b65 commit fd5fa01

File tree

1 file changed

+28
-18
lines changed

1 file changed

+28
-18
lines changed

library/core/src/slice/select.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,26 @@ fn partition_at_index_loop<'a, T, F>(
102102
}
103103
}
104104

105+
/// Helper function that returns the index of the minimum element in the slice using the given
106+
/// comparator function
107+
fn min_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
108+
slice
109+
.iter()
110+
.enumerate()
111+
.reduce(|acc, t| if is_less(t.1, acc.1) { t } else { acc })
112+
.map(|(i, _)| i)
113+
}
114+
115+
/// Helper function that returns the index of the maximum element in the slice using the given
116+
/// comparator function
117+
fn max_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
118+
slice
119+
.iter()
120+
.enumerate()
121+
.reduce(|acc, t| if is_less(acc.1, t.1) { t } else { acc })
122+
.map(|(i, _)| i)
123+
}
124+
105125
/// Reorder the slice such that the element at `index` is at its final sorted position.
106126
pub fn partition_at_index<T, F>(
107127
v: &mut [T],
@@ -120,13 +140,13 @@ where
120140
} else if index == v.len() - 1 {
121141
// Find max element and place it in the last position of the array. We're free to use
122142
// `unwrap()` here because we know v must not be empty.
123-
let (max_index, _) = v.iter().enumerate().max_by(from_is_less(&mut is_less)).unwrap();
124-
v.swap(max_index, index);
143+
let max_idx = max_index(v, &mut is_less).unwrap();
144+
v.swap(max_idx, index);
125145
} else if index == 0 {
126146
// Find min element and place it in the first position of the array. We're free to use
127147
// `unwrap()` here because we know v must not be empty.
128-
let (min_index, _) = v.iter().enumerate().min_by(from_is_less(&mut is_less)).unwrap();
129-
v.swap(min_index, index);
148+
let min_idx = min_index(v, &mut is_less).unwrap();
149+
v.swap(min_idx, index);
130150
} else {
131151
partition_at_index_loop(v, index, &mut is_less, None);
132152
}
@@ -137,16 +157,6 @@ where
137157
(left, pivot, right)
138158
}
139159

140-
/// helper function used to find the index of the min/max element
141-
/// using e.g. `slice.iter().enumerate().min_by(from_is_less(&mut is_less)).unwrap()`
142-
fn from_is_less<T>(
143-
is_less: &mut impl FnMut(&T, &T) -> bool,
144-
) -> impl FnMut(&(usize, &T), &(usize, &T)) -> cmp::Ordering + '_ {
145-
|&(_, x), &(_, y)| {
146-
if is_less(x, y) { cmp::Ordering::Less } else { cmp::Ordering::Greater }
147-
}
148-
}
149-
150160
/// Selection algorithm to select the k-th element from the slice in guaranteed O(n) time.
151161
/// This is essentially a quickselect that uses Tukey's Ninther for pivot selection
152162
fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut F, mut k: usize) {
@@ -170,14 +180,14 @@ fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut
170180
if k == v.len() - 1 {
171181
// Find max element and place it in the last position of the array. We're free to use
172182
// `unwrap()` here because we know v must not be empty.
173-
let (max_index, _) = v.iter().enumerate().max_by(from_is_less(is_less)).unwrap();
174-
v.swap(max_index, k);
183+
let max_idx = max_index(v, is_less).unwrap();
184+
v.swap(max_idx, k);
175185
return;
176186
} else if k == 0 {
177187
// Find min element and place it in the first position of the array. We're free to use
178188
// `unwrap()` here because we know v must not be empty.
179-
let (min_index, _) = v.iter().enumerate().min_by(from_is_less(is_less)).unwrap();
180-
v.swap(min_index, k);
189+
let min_idx = min_index(v, is_less).unwrap();
190+
v.swap(min_idx, k);
181191
return;
182192
}
183193

0 commit comments

Comments
 (0)