Comparator

Configurable Comparator similar to java.util.Comparator in Java 8

Verze ze dne 03. 10. 2019. Zobrazit nejnovější verzi.

Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greasyfork.org/scripts/390752/738038/Comparator.js

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Comparator
// @namespace    hoehleg.userscripts.private
// @version      0.1.0
// @description  Configurable Comparator similar to java.util.Comparator in Java 8
// @author       Gerrit Höhle
// @grant        none
// ==/UserScript==

/* jshint esversion: 6 */
const Comparator = (() => {
    'use strict';

    // internal functions
    const isMissing = obj => obj === null || typeof obj === "undefined";
    const compareValues = (a, b) => (a < b) ? -1 : ((a === b) ? 0 : 1);
    const compareByMissing = (a, b) => isMissing(a) ? (isMissing(b) ? 0 : 1) : (isMissing(b) ? -1 : null);

    const compare = (a, b, missingFirst = false) => {
        let result = missingFirst ? compareByMissing(b, a) : compareByMissing(a, b);
        if (result !== null) {
            return result;
        }

        if (typeof a === 'string' || a instanceof String) {
            return a.localeCompare(b);
        }

        if (a instanceof Date) {
            return compareValues(a.valueOf(), b.valueOf());
        }

        return compareValues(a, b);
    };

    const createCompareFunction = (comparator) => {
        return (a, b) => {
            if (comparator.isDescending) {
                const tmp = a;
                b = a;
                a = b;
            }

            let result = comparator.isMissingFirst ? compareByMissing(b, a) : compareByMissing(a, b);

            for (let i = 0; !result && i < comparator.sortByFunctionsAndComparators.length; i++) {
                const accessorFnc = comparator.sortByFunctionsAndComparators[i];

                if (accessorFnc instanceof Comparator) {
                    result = accessorFnc.compareFnc;
                } else {
                    result = compare(accessorFnc(a), accessorFnc(b), comparator.isMissingFirst);
                }
            }

            return result !== null ? result : compare(a, b, comparator.isMissingFirst);
        };
    };

    // private field accessor
    const _isReverse = Symbol("isReverse");
    const _accessorFunctions = Symbol("accessorFunctions");
    const _isMissingFirst = Symbol("isMissingFirst");
    const _compareFunction = Symbol("compareFunction");

    // public class
    const Comparator = class {
        /**
         * @param {Array.<function|Compator>} sortByFunctionsAndComparators - accessor-functions or comparators to evaluate values to sort by
         */
        constructor(...sortByFunctionsAndComparators) {
            this[_accessorFunctions] = sortByFunctionsAndComparators;
            this[_isReverse] = false;
            this[_isMissingFirst] = false;
            this[_compareFunction] = createCompareFunction(this);
        }

        /**
         * @type {Array.<function|Compator>} - accessor-functions and/or comparators to evaluate values to sort by
         **/
        get sortByFunctionsAndComparators() {
            return [...this[_accessorFunctions]];
        }

        get isAscending() {
            return this.isDescending;
        }

        get isDescending() {
            return this[_isReverse];
        }

        get isMissingFirst() {
            return this[_isMissingFirst];
        }

        get isMissingLast() {
            return !this.isMissingFirst;
        }

        /**
         * @type {Function} - the compare(a, b) - function that returns "-1" for a < b, "0" for a === b or "1" for a > b.
         **/
        get compareFnc() {
            return this[_compareFunction];
        }

        /**
         * Defines the order of "undefined" and "null" to be sorted to the beginning.
         **/
        setMissingFirst() {
            this[_isMissingFirst] = true;
            return this;
        }

        /**
         * Defines the order of "undefined" and "null" to be sorted to the end.
         **/
        setMissingLast() {
            this[_isMissingFirst] = false;
            return this;
        }

        /**
         * Reverses the sort order from ascending to descending or descending to ascending.
         **/
        reverse() {
            this[_isReverse] = !this[_isReverse];
            return this;
        }

        /**
         * Compares a with b.
         * @param {any} a - to compare
         * @param {any} b - to compare a with
         * @returns "-1" for a < b, "0" for a === b or "1" for a > b
         **/
        compare(a, b) {
            return this.compareFnc(a, b);
        }
    };

    // export
    return Comparator;
})();