Skip to content

Commit 4091cd0

Browse files
committed
Auto merge of #32693 - kamalmarhubi:binary_search_by_key, r=alexcrichton
collections: Add slice::binary_search_by_key This method adds to the family of `_by_key` methods, and is the counterpart of `slice::sort_by_key`. It was mentioned on #30423 but was not implemented at that time. Refs #30423
2 parents 76c1a0d + 62945b6 commit 4091cd0

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
2828

2929
#![cfg_attr(test, allow(deprecated))] // rand
30+
#![cfg_attr(not(test), feature(slice_binary_search_by_key))] // impl [T]
3031
#![cfg_attr(not(stage0), deny(warnings))]
3132

3233
#![feature(alloc)]

src/libcollections/slice.rs

+38
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,44 @@ impl<T> [T] {
741741
core_slice::SliceExt::binary_search_by(self, f)
742742
}
743743

744+
/// Binary search a sorted slice with a key extraction function.
745+
///
746+
/// Assumes that the slice is sorted by the key, for instance with
747+
/// `sort_by_key` using the same key extraction function.
748+
///
749+
/// If a matching value is found then returns `Ok`, containing the
750+
/// index for the matched element; if no match is found then `Err`
751+
/// is returned, containing the index where a matching element could
752+
/// be inserted while maintaining sorted order.
753+
///
754+
/// # Examples
755+
///
756+
/// Looks up a series of four elements in a slice of pairs sorted by
757+
/// their second elements. The first is found, with a uniquely
758+
/// determined position; the second and third are not found; the
759+
/// fourth could match any position in `[1,4]`.
760+
///
761+
/// ```rust
762+
/// #![feature(slice_binary_search_by_key)]
763+
/// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
764+
/// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
765+
/// (1, 21), (2, 34), (4, 55)];
766+
///
767+
/// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b), Ok(9));
768+
/// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b), Err(7));
769+
/// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
770+
/// let r = s.binary_search_by_key(&1, |&(a,b)| b);
771+
/// assert!(match r { Ok(1...4) => true, _ => false, });
772+
/// ```
773+
#[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "0")]
774+
#[inline]
775+
pub fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
776+
where F: FnMut(&T) -> B,
777+
B: Ord
778+
{
779+
core_slice::SliceExt::binary_search_by_key(self, b, f)
780+
}
781+
744782
/// Sorts the slice, in place.
745783
///
746784
/// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.

src/libcore/slice.rs

+13
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ pub trait SliceExt {
157157
fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
158158
#[stable(feature = "copy_from_slice", since = "1.9.0")]
159159
fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
160+
161+
#[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "0")]
162+
fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
163+
where F: FnMut(&Self::Item) -> B,
164+
B: Ord;
160165
}
161166

162167
// Use macros to be generic over const/mut
@@ -507,6 +512,14 @@ impl<T> SliceExt for [T] {
507512
src.as_ptr(), self.as_mut_ptr(), self.len());
508513
}
509514
}
515+
516+
#[inline]
517+
fn binary_search_by_key<B, F>(&self, b: &B, mut f: F) -> Result<usize, usize>
518+
where F: FnMut(&Self::Item) -> B,
519+
B: Ord
520+
{
521+
self.binary_search_by(|k| f(k).cmp(b))
522+
}
510523
}
511524

512525
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)