diff --git a/src/main/java/com/dashjoin/jsonata/Functions.java b/src/main/java/com/dashjoin/jsonata/Functions.java index c564805..b7d3ea2 100644 --- a/src/main/java/com/dashjoin/jsonata/Functions.java +++ b/src/main/java/com/dashjoin/jsonata/Functions.java @@ -1950,38 +1950,59 @@ public static List sort(List arr, Object comparator) { return arr; } - List result = new ArrayList<>(arr); if (comparator != null) { - Comparator comp = new Comparator() { - - @Override - public int compare(Object o1, Object o2) { - try { - Boolean swap = toBoolean(funcApply(comparator, Arrays.asList(o1, o2))); - if (swap == null) - return 0; - if (swap) - return 1; - else - return -1; - } catch (Throwable e) { - // TODO Auto-generated catch block - //e.printStackTrace(); - throw new RuntimeException(e); - } - } - - }; - if (comparator instanceof Comparator) - result.sort((Comparator)comparator); - else - result.sort((Comparator)comp); - } else { - result.sort(null); + if (comparator instanceof Comparator) { + List sorted = new ArrayList<>(arr); + sorted.sort((Comparator) comparator); + return sorted; + } + + Object[] sorted = arr.toArray(); + Object[] buffer = new Object[sorted.length]; + mergeSort(sorted, buffer, 0, sorted.length - 1, comparator); + List result = new ArrayList<>(sorted.length); + Collections.addAll(result, sorted); + return result; } - return result; + List sorted = new ArrayList<>(arr); + sorted.sort(null); + return sorted; + } + + private static void mergeSort(Object[] sorted, Object[] buffer, int lo, int hi, Object jsonataComparator) { + if (lo >= hi) { + return; + } + int mid = (lo + hi) / 2; + mergeSort(sorted, buffer, lo, mid, jsonataComparator); + mergeSort(sorted, buffer, mid + 1, hi, jsonataComparator); + merge(sorted, buffer, lo, mid, hi, jsonataComparator); + } + + private static void merge(Object[] sorted, Object[] buffer, int lo, int mid, int hi, Object jsonataComparator) { + int left = lo, right = mid + 1, writePos = lo; + + while (left <= mid && right <= hi) { + boolean swap; + try { + Boolean sw = toBoolean(funcApply(jsonataComparator, Arrays.asList(sorted[left], sorted[right]))); + swap = Boolean.TRUE.equals(sw); + } catch (Throwable e) { + throw new RuntimeException(e); + } + + if (swap) { + buffer[writePos++] = sorted[right++]; + } else { + buffer[writePos++] = sorted[left++]; + } + } + while (left <= mid) buffer[writePos++] = sorted[left++]; + while (right <= hi) buffer[writePos++] = sorted[right++]; + + System.arraycopy(buffer, lo, sorted, lo, hi - lo + 1); } /** diff --git a/src/test/java/com/dashjoin/jsonata/ArrayTest.java b/src/test/java/com/dashjoin/jsonata/ArrayTest.java index c97e7b2..ba03285 100644 --- a/src/test/java/com/dashjoin/jsonata/ArrayTest.java +++ b/src/test/java/com/dashjoin/jsonata/ArrayTest.java @@ -4,11 +4,14 @@ import static java.util.Arrays.asList; import static java.util.Map.of; import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class ArrayTest { @@ -83,4 +86,15 @@ public void testSortTypes() { e = jsonata("[{'value': 'b'}, {'value': 'a'}] ^(=" - }, { "name": "function-applications/case008.json", "ignoreError": true,