about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKevin Leimkuhler <kevin@kleimkuhler.com>2018-10-11 15:59:54 -0700
committerKevin Leimkuhler <kevin@kleimkuhler.com>2019-01-17 22:34:43 -0800
commit02477f6f99c22509825a85bd090e42f935b33983 (patch)
tree7aeca0eade74c1122439e2efe69c5589289512dd
parent8dea0d0172d5a50b75dbde8ece24201f0d5b2125 (diff)
downloadrust-02477f6f99c22509825a85bd090e42f935b33983.tar.gz
rust-02477f6f99c22509825a85bd090e42f935b33983.zip
Add is_sorted impl for [T]
-rw-r--r--src/libcore/iter/iterator.rs36
-rw-r--r--src/libcore/slice/mod.rs79
-rw-r--r--src/libcore/tests/slice.rs15
-rw-r--r--src/test/ui/feature-gates/feature-gate-is_sorted.rs2
4 files changed, 110 insertions, 22 deletions
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 6c3f8d91912..879cc8357cd 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -2608,19 +2608,18 @@ pub trait Iterator {
 
     /// Checks if the elements of this iterator are sorted.
     ///
-    /// That is, for each element `a` and its following element `b`, `a <= b`
-    /// must hold. If the iterator yields exactly zero or one element, `true`
-    /// is returned.
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// iterator yields exactly zero or one element, `true` is returned.
     ///
-    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above
-    /// definition implies that this function returns `false` if any two
-    /// consecutive items are not comparable.
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(is_sorted)]
-    /// 
+    ///
     /// assert!([1, 2, 2, 9].iter().is_sorted());
     /// assert!(![1, 3, 2, 4].iter().is_sorted());
     /// assert!([0].iter().is_sorted());
@@ -2636,13 +2635,11 @@ pub trait Iterator {
         self.is_sorted_by(|a, b| a.partial_cmp(b))
     }
 
-    /// Checks if the elements of this iterator are sorted using the given
-    /// comparator function.
+    /// Checks if the elements of this iterator are sorted using the given comparator function.
     ///
-    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given
-    /// `compare` function to determine the ordering of two elements. Apart from
-    /// that, it's equivalent to `is_sorted`; see its documentation for more
-    /// information.
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// `is_sorted`; see its documentation for more information.
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
     fn is_sorted_by<F>(mut self, mut compare: F) -> bool
     where
@@ -2664,19 +2661,18 @@ pub trait Iterator {
         true
     }
 
-    /// Checks if the elements of this iterator are sorted using the given
-    /// key extraction function.
+    /// Checks if the elements of this iterator are sorted using the given key extraction
+    /// function.
     ///
-    /// Instead of comparing the iterator's elements directly, this function
-    /// compares the keys of the elements, as determined by `f`. Apart from
-    /// that, it's equivalent to `is_sorted`; see its documentation for more
-    /// information.
+    /// Instead of comparing the iterator's elements directly, this function compares the keys of
+    /// the elements, as determined by `f`. Apart from that, it's equivalent to `is_sorted`; see
+    /// its documentation for more information.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(is_sorted)]
-    /// 
+    ///
     /// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
     /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
     /// ```
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 7fdc2acb8cc..d4cac3e4f4b 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1783,7 +1783,7 @@ impl<T> [T] {
     /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
     /// a[1..5].rotate_left(1);
     /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
-   /// ```
+    /// ```
     #[stable(feature = "slice_rotate", since = "1.26.0")]
     pub fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
@@ -2250,6 +2250,83 @@ impl<T> [T] {
              from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len))
         }
     }
+
+    /// Checks if the elements of this slice are sorted.
+    ///
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// slice yields exactly zero or one element, `true` is returned.
+    ///
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    /// let empty: [i32; 0] = [];
+    ///
+    /// assert!([1, 2, 2, 9].is_sorted());
+    /// assert!(![1, 3, 2, 4].is_sorted());
+    /// assert!([0].is_sorted());
+    /// assert!(empty.is_sorted());
+    /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    /// ```
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted(&self) -> bool
+    where
+        T: PartialOrd,
+    {
+        self.is_sorted_by(|a, b| a.partial_cmp(b))
+    }
+
+    /// Checks if the elements of this slice are sorted using the given comparator function.
+    ///
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// `is_sorted`; see its documentation for more information.
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
+    where
+        F: FnMut(&T, &T) -> Option<Ordering>
+    {
+        let mut last = match self.first() {
+            Some(e) => e,
+            None => return true,
+        };
+
+        for curr in &self[1..] {
+            if compare(&last, &curr).map(|o| o == Ordering::Greater).unwrap_or(true) {
+                return false;
+            }
+            last = &curr;
+        }
+
+        true
+    }
+
+    /// Checks if the elements of this slice are sorted using the given key extraction function.
+    ///
+    /// Instead of comparing the slice's elements directly, this function compares the keys of the
+    /// elements, as determined by `f`. Apart from that, it's equivalent to `is_sorted`; see its
+    /// documentation for more information.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+    /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    /// ```
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by_key<F, K>(&self, mut f: F) -> bool
+    where
+        F: FnMut(&T) -> K,
+        K: PartialOrd
+    {
+        self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+    }
 }
 
 #[lang = "slice_u8"]
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 2c96efbda76..e210e83122c 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1317,3 +1317,18 @@ fn test_copy_within_panics_src_inverted() {
     // 2 is greater than 1, so this range is invalid.
     bytes.copy_within(2..1, 0);
 }
+
+#[test]
+fn test_is_sorted() {
+    let empty: [i32; 0] = [];
+
+    assert!([1, 2, 2, 9].is_sorted());
+    assert!(![1, 3, 2].is_sorted());
+    assert!([0].is_sorted());
+    assert!(empty.is_sorted());
+    assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    assert!([-2, -1, 0, 3].is_sorted());
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    assert!(!["c", "bb", "aaa"].is_sorted());
+    assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
index 6b0f943b6c7..82fee379a4f 100644
--- a/src/test/ui/feature-gates/feature-gate-is_sorted.rs
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
@@ -13,4 +13,4 @@ fn main() {
     //^ ERROR: use of unstable library feature 'is_sorted'
     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
     //^ ERROR: use of unstable library feature 'is_sorted'
-}
\ No newline at end of file
+}