2019-06-17 07:55:54 -04:00
|
|
|
#[cfg(test)]
|
2019-08-01 23:57:23 +03:00
|
|
|
mod tests;
|
2019-06-17 07:55:54 -04:00
|
|
|
|
|
|
|
|
/// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The
|
|
|
|
|
/// `key_fn` extracts a key of type `K` from the data, and this
|
|
|
|
|
/// function finds the range of elements that match the key. `data`
|
|
|
|
|
/// must have been sorted as if by a call to `sort_by_key` for this to
|
|
|
|
|
/// work.
|
2021-12-05 20:17:35 -08:00
|
|
|
pub fn binary_search_slice<'d, E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E]
|
2019-06-17 07:55:54 -04:00
|
|
|
where
|
|
|
|
|
K: Ord,
|
|
|
|
|
{
|
2023-07-27 16:46:39 -07:00
|
|
|
let size = data.len();
|
|
|
|
|
let start = data.partition_point(|x| key_fn(x) < *key);
|
|
|
|
|
// At this point `start` either points at the first entry with equal or
|
|
|
|
|
// greater key or is equal to `size` in case all elements have smaller keys
|
|
|
|
|
if start == size || key_fn(&data[start]) != *key {
|
2022-02-19 00:48:49 +01:00
|
|
|
return &[];
|
2019-06-17 07:55:54 -04:00
|
|
|
};
|
|
|
|
|
|
2023-07-29 19:42:22 -07:00
|
|
|
// Find the first entry with key > `key`. Skip `start` entries since
|
|
|
|
|
// key_fn(&data[start]) == *key
|
|
|
|
|
let offset = start + 1;
|
|
|
|
|
let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset;
|
2019-06-17 07:55:54 -04:00
|
|
|
|
|
|
|
|
&data[start..end]
|
|
|
|
|
}
|