about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-04-14 21:23:35 -0700
committerbors <bors@rust-lang.org>2016-04-14 21:23:35 -0700
commit4091cd0c5d0aa6e915867ce996f5b547dee2ff31 (patch)
treef6bf5290fc6aceb7b899d81ed1430c829daa1940
parent76c1a0df2b59c56616bb44f9bee8ad394b391ba8 (diff)
parent62945b6ce3e2b504fdc14341e06d191d64788d72 (diff)
downloadrust-4091cd0c5d0aa6e915867ce996f5b547dee2ff31.tar.gz
rust-4091cd0c5d0aa6e915867ce996f5b547dee2ff31.zip
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
-rw-r--r--src/libcollections/lib.rs1
-rw-r--r--src/libcollections/slice.rs38
-rw-r--r--src/libcore/slice.rs13
3 files changed, 52 insertions, 0 deletions
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 7540c51e236..88b3517fe71 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -27,6 +27,7 @@
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
 
 #![cfg_attr(test, allow(deprecated))] // rand
+#![cfg_attr(not(test), feature(slice_binary_search_by_key))] // impl [T]
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(alloc)]
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index db91d911c73..07db33c6be8 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -741,6 +741,44 @@ impl<T> [T] {
         core_slice::SliceExt::binary_search_by(self, f)
     }
 
+    /// Binary search a sorted slice with a key extraction function.
+    ///
+    /// Assumes that the slice is sorted by the key, for instance with
+    /// `sort_by_key` using the same key extraction function.
+    ///
+    /// If a matching value is found then returns `Ok`, containing the
+    /// index for the matched element; if no match is found then `Err`
+    /// is returned, containing the index where a matching element could
+    /// be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements in a slice of pairs sorted by
+    /// their second elements. The first is found, with a uniquely
+    /// determined position; the second and third are not found; the
+    /// fourth could match any position in `[1,4]`.
+    ///
+    /// ```rust
+    /// #![feature(slice_binary_search_by_key)]
+    /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
+    ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+    ///          (1, 21), (2, 34), (4, 55)];
+    ///
+    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
+    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
+    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
+    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "0")]
+    #[inline]
+    pub fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
+        where F: FnMut(&T) -> B,
+              B: Ord
+    {
+        core_slice::SliceExt::binary_search_by_key(self, b, f)
+    }
+
     /// Sorts the slice, in place.
     ///
     /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 2e91238bff3..68f5a725b74 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -157,6 +157,11 @@ pub trait SliceExt {
     fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
+
+    #[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "0")]
+    fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
+        where F: FnMut(&Self::Item) -> B,
+              B: Ord;
 }
 
 // Use macros to be generic over const/mut
@@ -507,6 +512,14 @@ impl<T> SliceExt for [T] {
                 src.as_ptr(), self.as_mut_ptr(), self.len());
         }
     }
+
+    #[inline]
+    fn binary_search_by_key<B, F>(&self, b: &B, mut f: F) -> Result<usize, usize>
+        where F: FnMut(&Self::Item) -> B,
+              B: Ord
+    {
+        self.binary_search_by(|k| f(k).cmp(b))
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]