This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new d86c0d3f11 GROOVY-11653: Create DGM#sort(List) and AGM#sort(T[])
variants that take an IntRange
d86c0d3f11 is described below
commit d86c0d3f11c537853c994619c283963bfd6f5478
Author: Paul King <[email protected]>
AuthorDate: Tue May 6 14:56:24 2025 +1000
GROOVY-11653: Create DGM#sort(List) and AGM#sort(T[]) variants that take an
IntRange
---
.../groovy/runtime/ArrayGroovyMethods.java | 80 +++++++++++++++++++-
.../groovy/runtime/DefaultGroovyMethods.java | 88 +++++++++++++++++++++-
2 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java
b/src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java
index e0ac6bd481..6a3dd0b42b 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java
@@ -8107,7 +8107,7 @@ public class ArrayGroovyMethods extends
DefaultGroovyMethodsSupport {
}
/**
- * Modifies this array so that its elements are in sorted order as
determined by the given comparator.
+ * Sorts the elements from this array into sorted order as determined by
the given comparator.
* If mutate is true, the array is sorted in place and returned.
Otherwise, a new sorted
* array is returned and the original array remains unchanged.
* <pre class="groovyTestCase">
@@ -8151,7 +8151,26 @@ public class ArrayGroovyMethods extends
DefaultGroovyMethodsSupport {
}
/**
- * Modifies this array so that its elements are in sorted order using the
Closure to determine the correct ordering.
+ * Sorts the elements from this array with index values in the given index
range
+ * into a newly created array using the Closure to determine the correct
ordering.
+ * <p>
+ * If the closure has two parameters it is used like a traditional
Comparator. I.e. it should compare
+ * its two parameters for order, returning a negative integer, zero, or a
positive integer when the
+ * first parameter is less than, equal to, or greater than the second
respectively. Otherwise,
+ * the Closure is assumed to take a single parameter and return a
Comparable (typically an Integer)
+ * which is then used for further comparison.
+ *
+ * @param self the array containing the elements to be sorted
+ * @param closure a Closure used to determine the correct ordering
+ * @return the sorted array
+ * @since 5.0.0
+ */
+ public static <T> T[] sort(T[] self, IntRange range,
@ClosureParams(value=FromString.class,options={"T","T,T"}) Closure<?> closure) {
+ return sort(self, range, false, closure);
+ }
+
+ /**
+ * Sorts the elements from this array into sorted order using the Closure
to determine the correct ordering.
* If mutate is false, a new array is returned and the original array
remains unchanged.
* Otherwise, the original array is sorted in place and returned.
* <p>
@@ -8170,7 +8189,7 @@ public class ArrayGroovyMethods extends
DefaultGroovyMethodsSupport {
* </pre>
*
* @param self the array to be sorted
- * @param mutate false will always cause a new array to be created, true
will mutate arrays in place
+ * @param mutate false causes a new array to be created, true will mutate
arrays in place
* @param closure a Closure used to determine the correct ordering
* @return the sorted array
* @since 1.8.1
@@ -8182,6 +8201,61 @@ public class ArrayGroovyMethods extends
DefaultGroovyMethodsSupport {
return self;
}
+ /**
+ * Sorts the elements with index values in the given index range
+ * into sorted order using the Closure to determine the correct ordering.
+ * If mutate is false, a new array is returned and the original array
remains unchanged.
+ * Otherwise, the original array is sorted in place and returned.
+ * <p>
+ * If the closure has two parameters it is used like a traditional
Comparator. I.e. it should compare
+ * its two parameters for order, returning a negative integer, zero, or a
positive integer when the
+ * first parameter is less than, equal to, or greater than the second
respectively. Otherwise,
+ * the Closure is assumed to take a single parameter and return a
Comparable (typically an Integer)
+ * which is then used for further comparison.
+ * <pre class="groovyTestCase">
+ * // an array with some odd then even numbers
+ * Integer[] nums = [5, 9, 1, 7, 3, 4, 8, 6, 0, 2]
+ *
+ * // sort odds ascending, evens descending
+ * assert nums.sort(0..4, false) { it }.sort(5..9, false) { -it }
+ * == [1, 3, 5, 7, 9, 8, 6, 4, 2, 0]
+ * // sort odds descending, evens descending
+ * assert nums.sort(0..<5, false) { -it }.sort(4<..<10, false) {
-it }
+ * == [9, 7, 5, 3, 1, 8, 6, 4, 2, 0]
+ * // sort odds descending, evens ascending
+ * assert nums.sort(0..<5, false) { -it }.sort(5..-1, false) { it }
+ * == [9, 7, 5, 3, 1, 0, 2, 4, 6, 8]
+ * // leave first and last numbers, sort remaining odds ascending,
remaining evens descending
+ * assert nums.sort(1..4, false) { it }.sort(5..-2, false) { -it }
+ * == [5, 1, 3, 7, 9, 8, 6, 4, 0, 2]
+ * // leave first and last numbers, sort remaining odds descending,
remaining evens ascending
+ * assert nums.sort(1..4, false) { -it }.sort(5..-2, false) { it }
+ * == [5, 9, 7, 3, 1, 0, 4, 6, 8, 2]
+ * // leave first and last odds and evens, sort remaining odds ascending,
remaining evens descending
+ * assert nums.sort(0<..<4, false) { it }.sort(5<..<9, false)
{ -it }
+ * == [5, 1, 7, 9, 3, 4, 8, 6, 0, 2]
+ * // leave first and last odds and evens, sort remaining odds descending,
remaining evens ascending
+ * assert nums.sort(0<..<4, false) { -it }.sort(5<..<-1,
false) { it }
+ * == [5, 9, 7, 1, 3, 4, 0, 6, 8, 2]
+ * </pre>
+ *
+ * @param self the array to be sorted
+ * @param range the inclusive range of index values over which to sort
+ * @param mutate false causes a new array to be created, true will mutate
arrays in place
+ * @param closure a Closure used to determine the correct ordering
+ * @return the sorted array
+ * @since 5.0.0
+ */
+ public static <T> T[] sort(T[] self, IntRange range, boolean mutate,
@ClosureParams(value=FromString.class,options={"T","T,T"}) Closure<?> closure) {
+ Objects.requireNonNull(self);
+ RangeInfo info = range.subListBorders(self.length);
+ Objects.checkFromToIndex(info.from, info.to, self.length);
+ if (!mutate) self = self.clone();
+ Comparator<T> c = closure.getMaximumNumberOfParameters() == 1 ? new
OrderBy<>(closure) : new ClosureComparator<>(closure);
+ Arrays.sort(self, info.from, info.to, c);
+ return self;
+ }
+
//--------------------------------------------------------------------------
// split
diff --git
a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index c47078861e..1f26369fcc 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -13455,7 +13455,7 @@ public class DefaultGroovyMethods extends
DefaultGroovyMethodsSupport {
* </pre>
*
* @param self the Iterable to be sorted
- * @param mutate false will always cause a new list to be created,
true will mutate lists in place
+ * @param mutate false causes a new list to be created, true will
mutate lists in place
* @param comparator a Comparator used for the comparison
* @return a sorted List
* @since 2.2.0
@@ -13466,6 +13466,78 @@ public class DefaultGroovyMethods extends
DefaultGroovyMethodsSupport {
return list;
}
+ /**
+ * Sorts elements in the given index range using the given Closure to
determine the ordering.
+ * If mutate is true, it is sorted in place and returned. Otherwise, the
elements are first placed
+ * into a new list which is then sorted and returned, leaving the original
List unchanged.
+ *
+ * <pre class="groovyTestCase">
+ * // a list with some odd then even numbers
+ * def nums = [5, 9, 1, 7, 3, 4, 8, 6, 0, 2]
+ *
+ * // sort odds ascending, evens descending
+ * assert nums.sort(0..4, false) { it }.sort(5..9, false) { -it }
+ * == [1, 3, 5, 7, 9, 8, 6, 4, 2, 0]
+ * // sort odds descending, evens descending
+ * assert nums.sort(0..<5, false) { -it }.sort(4<..<10, false) {
-it }
+ * == [9, 7, 5, 3, 1, 8, 6, 4, 2, 0]
+ * // sort odds descending, evens ascending
+ * assert nums.sort(0..<5, false) { -it }.sort(5..-1, false) { it }
+ * == [9, 7, 5, 3, 1, 0, 2, 4, 6, 8]
+ * // leave first and last numbers, sort remaining odds ascending,
remaining evens descending
+ * assert nums.sort(1..4, false) { it }.sort(5..-2, false) { -it }
+ * == [5, 1, 3, 7, 9, 8, 6, 4, 0, 2]
+ * // leave first and last numbers, sort remaining odds descending,
remaining evens ascending
+ * assert nums.sort(1..4, false) { -it }.sort(5..-2, false) { it }
+ * == [5, 9, 7, 3, 1, 0, 4, 6, 8, 2]
+ * // leave first and last odds and evens, sort remaining odds ascending,
remaining evens descending
+ * assert nums.sort(0<..<4, false) { it }.sort(5<..<9, false)
{ -it }
+ * == [5, 1, 7, 9, 3, 4, 8, 6, 0, 2]
+ * // leave first and last odds and evens, sort remaining odds descending,
remaining evens ascending
+ * assert nums.sort(0<..<4, false) { -it }.sort(5<..<-1,
false) { it }
+ * == [5, 9, 7, 1, 3, 4, 0, 6, 8, 2]
+ * </pre>
+ *
+ * @param self the List to be sorted
+ * @param range the inclusive range of index values over which to sort
+ * @param mutate false causes a new list to be created, true will mutate
lists in place
+ * @param closure a Closure used to determine the correct ordering
+ * @return a sorted List
+ * @since 5.0.0
+ */
+ public static <T> List<T> sort(List<T> self, IntRange range, boolean
mutate, @ClosureParams(value=FromString.class,options={"T","T,T"}) Closure<?>
closure) {
+ Objects.requireNonNull(self);
+ RangeInfo info = range.subListBorders(self.size());
+ Objects.checkFromToIndex(info.from, info.to, self.size());
+ T[] a = (T[]) self.toArray();
+ Comparator<T> c = closure.getMaximumNumberOfParameters() == 1 ? new
OrderBy<>(closure) : new ClosureComparator<>(closure);
+ Arrays.sort(a, info.from, info.to, c);
+ if (!mutate) {
+ return Arrays.asList(a);
+ }
+ ListIterator<T> i = self.listIterator();
+ for (T e : a) {
+ i.next();
+ i.set(e);
+ }
+ return self;
+ }
+
+ /**
+ * A sort variant that takes an index range and always mutates the
original list.
+ * <pre class="groovyTestCase">
+ * def nums = [5, 9, 1, 7, 3, 4, 8, 6, 0, 2]
+ * nums.sort(0..4) { it }
+ * assert nums == [1, 3, 5, 7, 9, 4, 8, 6, 0, 2]
+ * </pre>
+ *
+ * @see #sort(List, IntRange, boolean, Closure)
+ * @return the sorted list
+ */
+ public static <T> List<T> sort(List<T> self, IntRange range,
@ClosureParams(value=FromString.class,options={"T","T,T"}) Closure<?> closure) {
+ return sort(self, range, true, closure);
+ }
+
/**
* Sorts the given iterator items into a sorted iterator using the Closure
to determine the correct ordering.
* The original iterator will be fully processed after the method call.
@@ -15227,6 +15299,20 @@ public class DefaultGroovyMethods extends
DefaultGroovyMethodsSupport {
return toSorted(self, comparator);
}
+ /**
+ * A sort variant that takes an index range and never modifies the
original list.
+ * <pre class="groovyTestCase">
+ * def nums = [5, 9, 1, 7, 3, 4, 8, 6, 0, 2]
+ * assert nums.toSorted(0..4) { it } == [1, 3, 5, 7, 9, 4, 8, 6, 0, 2]
+ * </pre>
+ *
+ * @see #sort(List, IntRange, boolean, Closure)
+ * @return the sorted list
+ */
+ public static <T> List<T> toSorted(List<T> self, IntRange range,
@ClosureParams(value=FromString.class,options={"T","T,T"}) Closure<?> closure) {
+ return sort(self, range, false, closure);
+ }
+
/**
* Sorts the elements from the given map into a new ordered map using
* a {@link NumberAwareComparator} on map entry values to determine the
resulting order.