221 lines
6.7 KiB
JavaScript
221 lines
6.7 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
'use strict';
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.remove = exports.insert = exports.index = exports.fill = exports.range = exports.flatten = exports.commonPrefixLength = exports.first = exports.firstIndex = exports.uniqueFilter = exports.distinct = exports.isFalsyOrEmpty = exports.move = exports.coalesce = exports.top = exports.findFirst = exports.binarySearch = exports.equals = exports.tail = void 0;
|
|
/**
|
|
* Returns the last element of an array.
|
|
* @param array The array.
|
|
* @param n Which element from the end (default ist zero).
|
|
*/
|
|
function tail(array, n = 0) {
|
|
return array[array.length - (1 + n)];
|
|
}
|
|
exports.tail = tail;
|
|
function equals(one, other, itemEquals = (a, b) => a === b) {
|
|
if (one.length !== other.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0, len = one.length; i < len; i++) {
|
|
if (!itemEquals(one[i], other[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
exports.equals = equals;
|
|
function binarySearch(array, key, comparator) {
|
|
let low = 0, high = array.length - 1;
|
|
while (low <= high) {
|
|
let mid = ((low + high) / 2) | 0;
|
|
let comp = comparator(array[mid], key);
|
|
if (comp < 0) {
|
|
low = mid + 1;
|
|
}
|
|
else if (comp > 0) {
|
|
high = mid - 1;
|
|
}
|
|
else {
|
|
return mid;
|
|
}
|
|
}
|
|
return -(low + 1);
|
|
}
|
|
exports.binarySearch = binarySearch;
|
|
/**
|
|
* Takes a sorted array and a function p. The array is sorted in such a way that all elements where p(x) is false
|
|
* are located before all elements where p(x) is true.
|
|
* @returns the least x for which p(x) is true or array.length if no element fullfills the given function.
|
|
*/
|
|
function findFirst(array, p) {
|
|
let low = 0, high = array.length;
|
|
if (high === 0) {
|
|
return 0; // no children
|
|
}
|
|
while (low < high) {
|
|
let mid = Math.floor((low + high) / 2);
|
|
if (p(array[mid])) {
|
|
high = mid;
|
|
}
|
|
else {
|
|
low = mid + 1;
|
|
}
|
|
}
|
|
return low;
|
|
}
|
|
exports.findFirst = findFirst;
|
|
/**
|
|
* Returns the top N elements from the array.
|
|
*
|
|
* Faster than sorting the entire array when the array is a lot larger than N.
|
|
*
|
|
* @param array The unsorted array.
|
|
* @param compare A sort function for the elements.
|
|
* @param n The number of elements to return.
|
|
* @return The first n elemnts from array when sorted with compare.
|
|
*/
|
|
function top(array, compare, n) {
|
|
if (n === 0) {
|
|
return [];
|
|
}
|
|
const result = array.slice(0, n).sort(compare);
|
|
for (let i = n, m = array.length; i < m; i++) {
|
|
const element = array[i];
|
|
if (compare(element, result[n - 1]) < 0) {
|
|
result.pop();
|
|
const j = findFirst(result, e => compare(element, e) < 0);
|
|
result.splice(j, 0, element);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
exports.top = top;
|
|
/**
|
|
* @returns a new array with all undefined or null values removed. The original array is not modified at all.
|
|
*/
|
|
function coalesce(array) {
|
|
if (!array) {
|
|
return array;
|
|
}
|
|
return array.filter(e => !!e);
|
|
}
|
|
exports.coalesce = coalesce;
|
|
/**
|
|
* Moves the element in the array for the provided positions.
|
|
*/
|
|
function move(array, from, to) {
|
|
array.splice(to, 0, array.splice(from, 1)[0]);
|
|
}
|
|
exports.move = move;
|
|
/**
|
|
* @returns {{false}} if the provided object is an array
|
|
* and not empty.
|
|
*/
|
|
function isFalsyOrEmpty(obj) {
|
|
return !Array.isArray(obj) || obj.length === 0;
|
|
}
|
|
exports.isFalsyOrEmpty = isFalsyOrEmpty;
|
|
/**
|
|
* Removes duplicates from the given array. The optional keyFn allows to specify
|
|
* how elements are checked for equalness by returning a unique string for each.
|
|
*/
|
|
function distinct(array, keyFn) {
|
|
if (!keyFn) {
|
|
return array.filter((element, position) => {
|
|
return array.indexOf(element) === position;
|
|
});
|
|
}
|
|
const seen = Object.create(null);
|
|
return array.filter((elem) => {
|
|
const key = keyFn(elem);
|
|
if (seen[key]) {
|
|
return false;
|
|
}
|
|
seen[key] = true;
|
|
return true;
|
|
});
|
|
}
|
|
exports.distinct = distinct;
|
|
function uniqueFilter(keyFn) {
|
|
const seen = Object.create(null);
|
|
return element => {
|
|
const key = keyFn(element);
|
|
if (seen[key]) {
|
|
return false;
|
|
}
|
|
seen[key] = true;
|
|
return true;
|
|
};
|
|
}
|
|
exports.uniqueFilter = uniqueFilter;
|
|
function firstIndex(array, fn) {
|
|
for (let i = 0; i < array.length; i++) {
|
|
const element = array[i];
|
|
if (fn(element)) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
exports.firstIndex = firstIndex;
|
|
function first(array, fn, notFoundValue = null) {
|
|
const index = firstIndex(array, fn);
|
|
return index < 0 ? notFoundValue : array[index];
|
|
}
|
|
exports.first = first;
|
|
function commonPrefixLength(one, other, equals = (a, b) => a === b) {
|
|
let result = 0;
|
|
for (let i = 0, len = Math.min(one.length, other.length); i < len && equals(one[i], other[i]); i++) {
|
|
result++;
|
|
}
|
|
return result;
|
|
}
|
|
exports.commonPrefixLength = commonPrefixLength;
|
|
function flatten(arr) {
|
|
return arr.reduce((r, v) => r.concat(v), []);
|
|
}
|
|
exports.flatten = flatten;
|
|
function range(to, from = 0) {
|
|
const result = [];
|
|
for (let i = from; i < to; i++) {
|
|
result.push(i);
|
|
}
|
|
return result;
|
|
}
|
|
exports.range = range;
|
|
function fill(num, valueFn, arr = []) {
|
|
for (let i = 0; i < num; i++) {
|
|
arr[i] = valueFn();
|
|
}
|
|
return arr;
|
|
}
|
|
exports.fill = fill;
|
|
function index(array, indexer, merger = t => t) {
|
|
return array.reduce((r, t) => {
|
|
const key = indexer(t);
|
|
r[key] = merger(t, r[key]);
|
|
return r;
|
|
}, Object.create(null));
|
|
}
|
|
exports.index = index;
|
|
/**
|
|
* Inserts an element into an array. Returns a function which, when
|
|
* called, will remove that element from the array.
|
|
*/
|
|
function insert(array, element) {
|
|
array.push(element);
|
|
return () => {
|
|
const index = array.indexOf(element);
|
|
if (index > -1) {
|
|
array.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
exports.insert = insert;
|
|
function remove(array, element) {
|
|
array.splice(array.indexOf(element));
|
|
}
|
|
exports.remove = remove;
|
|
//# sourceMappingURL=arrays.js.map
|