Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 77 additions & 3 deletions src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java
Original file line number Diff line number Diff line change
Expand Up @@ -8107,7 +8107,7 @@ public static <T> T[] sort(T[] self, Comparator<? super T> comparator) {
}

/**
* 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">
Expand Down Expand Up @@ -8151,7 +8151,26 @@ public static <T> T[] sort(T[] self, @ClosureParams(value=FromString.class,optio
}

/**
* 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>
Expand All @@ -8170,7 +8189,7 @@ public static <T> T[] sort(T[] self, @ClosureParams(value=FromString.class,optio
* </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
Expand All @@ -8182,6 +8201,61 @@ public static <T> T[] sort(T[] self, boolean mutate, @ClosureParams(value=FromSt
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..&lt;5, false) { -it }.sort(4&lt;..&lt;10, false) { -it }
* == [9, 7, 5, 3, 1, 8, 6, 4, 2, 0]
* // sort odds descending, evens ascending
* assert nums.sort(0..&lt;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&lt;..&lt;4, false) { it }.sort(5&lt;..&lt;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&lt;..&lt;4, false) { -it }.sort(5&lt;..&lt;-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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13428,7 +13428,7 @@ public static <T> Iterator<T> sort(Iterator<T> self, Comparator<? super T> compa
* </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
Expand All @@ -13439,6 +13439,78 @@ public static <T> List<T> sort(Iterable<T> self, boolean mutate, Comparator<? su
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..&lt;5, false) { -it }.sort(4&lt;..&lt;10, false) { -it }
* == [9, 7, 5, 3, 1, 8, 6, 4, 2, 0]
* // sort odds descending, evens ascending
* assert nums.sort(0..&lt;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&lt;..&lt;4, false) { it }.sort(5&lt;..&lt;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&lt;..&lt;4, false) { -it }.sort(5&lt;..&lt;-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.
Expand Down Expand Up @@ -15200,6 +15272,20 @@ public static <T> Iterator<T> toSorted(Iterator<T> self, @ClosureParams(value=Fr
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.
Expand Down