import { isPromise } from "./rp.ts"; export function evalPromiseValues(vals: any[]): Promise | any[] { const promises = []; const promiseResults = new Array(vals.length); for (let i = 0; i < vals.length; i++) { if (isPromise(vals[i])) { promises.push( (vals[i] as Promise).then((v: any) => (promiseResults[i] = v)), ); } else { promiseResults[i] = vals[i]; } } if (promises.length === 0) { return promiseResults; } return Promise.all(promises).then(() => promiseResults); } /** * return the mid value among x, y, and z * @param x * @param y * @param z * @param compare * @returns {Promise.<*>} */ async function getPivot( x: any, y: any, z: any, compare: (a: any, b: any) => Promise, ) { if ((await compare(x, y)) < 0) { if ((await compare(y, z)) < 0) { return y; } if ((await compare(z, x)) < 0) { return x; } return z; } if ((await compare(y, z)) > 0) { return y; } if ((await compare(z, x)) > 0) { return x; } return z; } /** * asynchronous quick sort * @param arr array to sort * @param compare asynchronous comparing function * @param left index where the range of elements to be sorted starts * @param right index where the range of elements to be sorted ends * @returns {Promise.<*>} */ export async function asyncQuickSort( arr: any[], compare: (a: any, b: any) => Promise, left = 0, right = arr.length - 1, ) { if (left < right) { let i = left, j = right, tmp; const pivot = await getPivot( arr[i], arr[i + Math.floor((j - i) / 2)], arr[j], compare, ); while (true) { while ((await compare(arr[i], pivot)) < 0) { i++; } while ((await compare(pivot, arr[j])) < 0) { j--; } if (i >= j) { break; } tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; i++; j--; } await asyncQuickSort(arr, compare, left, i - 1); await asyncQuickSort(arr, compare, j + 1, right); } return arr; } /** * iterative async merge sort * @param arr tagged array of { val, idx } elements * @param compare async comparator returning <0, 0, or >0 */ export async function asyncMergeSort( arr: { val: any; idx: number }[], compare: ( a: { val: any; idx: number }, b: { val: any; idx: number }, ) => Promise, ): Promise { const n = arr.length; if (n <= 1) return; const work = new Array(n); for (let size = 1; size < n; size *= 2) { for (let left = 0; left < n; left += 2 * size) { const mid = Math.min(left + size, n); const right = Math.min(left + 2 * size, n); let i = left, j = mid, k = left; while (i < mid && j < right) { const cmp = await compare(arr[i], arr[j]); if (cmp <= 0) work[k++] = arr[i++]; else work[k++] = arr[j++]; } while (i < mid) work[k++] = arr[i++]; while (j < right) work[k++] = arr[j++]; for (let m = left; m < right; m++) arr[m] = work[m]; } } }