about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKamal Marhubi <kamal@marhubi.com>2016-03-22 21:26:57 -0400
committerKamal Marhubi <kamal@marhubi.com>2016-04-12 10:31:02 -0400
commit62945b6ce3e2b504fdc14341e06d191d64788d72 (patch)
tree74fdf757e1772ef77e9f3ae02f9cb6ec9f675255
parentbed32d83fcd1337e962a58fd04fae6b8503e3283 (diff)
downloadrust-62945b6ce3e2b504fdc14341e06d191d64788d72.tar.gz
rust-62945b6ce3e2b504fdc14341e06d191d64788d72.zip
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")]