Comparator

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

Version au 03/10/2019. Voir la dernière version.

Ce script ne doit pas être installé directement. C'est une librairie destinée à être incluse dans d'autres scripts avec la méta-directive // @require https://update.greatest.deepsurf.us/scripts/390752/738034/Comparator.js

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Comparator
// @namespace    hoehleg.userscripts.private
// @version      0.1
// @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.isReverse) {
                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[_isReverse];
        }

        get isDescending() {
            return !this.isAscending;
        }

        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;
})();