rx-player
Version:
Canal+ HTML5 Video Player
241 lines (222 loc) • 7.08 kB
text/typescript
/**
* Copyright 2015 CANAL+ Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import arrayFind from "./array_find";
import arrayIncludes from "./array_includes";
/**
* Creates an Array automatically sorted with the sorting function given to the
* constructor when the add method is called.
*
* @example
* ```js
* const sortedList = new SortedList((a, b) => a.start - b.start);
* const element1 = { start: 20 };
* const element2 = { start: 10 };
* const element3 = { start: 15 };
*
* sortedList.add(element1, element2);
* console.log(sortedList.unwrap());
* // -> [{ start: 10 }, { start : 20 }]
*
* sortedList.add(element3);
* console.log(sortedList.unwrap());
* // -> [{ start: 10 }, { start : 15 }, { start: 20 }]
*
* sortedList.removeElement(element2);
* // -> [{ start: 10 }, { start: 15 }]
* ```
* @class SortedList
*/
export default class SortedList<T> {
private readonly _sortingFn: (a: T, b: T) => number;
private _array: T[];
/**
* @param {Function} sortingFunction
*/
constructor(sortingFunction: (a: T, b: T) => number) {
this._array = [];
this._sortingFn = sortingFunction;
}
/**
* Add a new element to the List at the right place for the List to stay
* sorted.
*
* /!\ The added Element will share the same reference than the given
* argument, any mutation on your part can lead to an un-sorted SortedList.
* You can still re-force the sorting to happen by calling forceSort.
* @param {...*} elements
*/
public add(...elements: T[]): void {
elements.sort(this._sortingFn);
let j = 0;
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
let inserted = false;
while (!inserted && j < this._array.length) {
if (this._sortingFn(element, this._array[j]) < 0) {
this._array.splice(j, 0, element);
inserted = true;
} else {
j++;
}
}
if (!inserted) {
this._array.push(element);
}
}
}
/**
* Returns the current length of the list.
* @returns {number}
*/
public length(): number {
return this._array.length;
}
/**
* Returns the nth element. Throws if the index does not exist.
*
* /!\ The returned Element shares the same reference with what is used
* internally, any mutation on your part can lead to an un-sorted SortedList.
* You can still re-force the sorting to happen by calling forceSort.
* @throws Error - Throws if the given index is negative or superior to the
* array's length.
* @param {number} index
* @returns {*}
*/
public get(index: number): T {
if (index < 0 || index >= this._array.length) {
throw new Error("Invalid index.");
}
return this._array[index];
}
public toArray(): T[] {
return this._array.slice();
}
/**
* Find the first element corresponding to the given predicate.
*
* /!\ The returned element shares the same reference with what is used
* internally, any mutation on your part can lead to an un-sorted SortedList.
* You can still re-force the sorting to happen by calling forceSort.
* @param {Function} fn
* @returns {*}
*/
public findFirst(fn: (element: T) => boolean): T | undefined {
return arrayFind(this._array, fn);
}
/**
* Returns true if the List contains the given element.
* @param {*} element
* @returns {Boolean}
*/
public has(element: T): boolean {
return arrayIncludes(this._array, element);
}
/**
* Remove the first occurence of the given element.
* Returns the index of the removed element. Undefined if not found.
* @returns {number|undefined}
*/
public removeElement(element: T): number | undefined {
const indexOf = this._array.indexOf(element);
if (indexOf >= 0) {
this._array.splice(indexOf, 1);
return indexOf;
}
return undefined;
}
/**
* Returns the first element.
*
* /!\ The returned Element shares the same reference with what is used
* internally, any mutation on your part can lead to an un-sorted SortedList.
* You can still re-force the sorting to happen by calling forceSort.
* @returns {*}
*/
public head(): T | undefined {
return this._array[0];
}
/**
* Returns the last element.
*
* /!\ The returned Element shares the same reference with what is used
* internally, any mutation on your part can lead to an un-sorted SortedList.
* You can still re-force the sorting to happen by calling forceSort.
* @returns {*}
*/
public last(): T | undefined {
return this._array[this._array.length - 1];
}
/**
* Remove the first element.
* Returns the element removed or undefined if no element were removed.
* @returns {*}
*/
public shift(): T | undefined {
return this._array.shift();
}
/**
* Remove the last element.
* Returns the element removed or undefined if no element were removed.
* @returns {*}
*/
public pop(): T | undefined {
return this._array.pop();
}
/**
* Returns true if the wrapped Array is well-sorted.
*
* You might want to call this function to know if a mutation you've done
* yourself impacted the order of elements.
* You can then call the forceSort function to sort the list manually.
*
* @example
* ```js
* const sortedList = new SortedList((a, b) => a.start - b.start);
* const element1 = { start: 20 };
* const element2 = { start: 10 };
*
* sortedList.add(element1, element2);
* console.log(sortedList.unwrap()); // -> [{ start: 10 }, { start : 20 }]
* console.log(sortedList.checkSort()); // -> true
*
* element2.start = 5; // Mutation impacting the order of elements
* console.log(sortedList.unwrap()); // -> [{ start: 10 }, { start : 5 }]
* console.log(sortedList.checkSort()); // -> false
*
* sortedList.forceSort();
* console.log(sortedList.unwrap()); // -> [{ start: 5 }, { start : 10 }]
* console.log(sortedList.checkSort()); // -> true
* ```
* @returns {Boolean}
*/
// checkSort() : boolean {
// for (let i = 0; i < this._array.length - 1; i++) {
// if (this._sortingFn(this._array[i], this._array[i + 1]) > 0) {
// return false;
// }
// }
// return true;
// }
/**
* Force the array to be sorted.
*
* You might want to call this function when you're unsure that a mutation
* you've done yourself impacted the order of the elements in the list.
*/
// forceSort() {
// this._array.sort(this._sortingFn);
// }
}