miramiku
4/8/2017 - 8:17 AM

SetOp.js

/** @summary 集合演算を提供する */
var SetOp = ( function () {
  "use strict";

  var _compare = function ( a, b ) {
      return a === b ? 0 : a < b ? -1 : 1;
    },
    _base = function ( operator ) {
      var a = [],
        b = [],
        i = 0,
        j = 0,
        result = [],

        operation = {
          intersection: {
            equal: function () {
              result.push( a[ i ] );
            },
            lesser: function () {},
            greater: function () {},
            result: function () {
              return result;
            }
          },
          difference: {
            equal: function () {},
            lesser: function () {
              result.push( a[ i ] );
            },
            greater: function () {},
            result: function () {
              return result.concat( a.slice( i ) );
            }
          },
          union: {
            equal: function () {
              result.push( a[ i ] );
            },
            lesser: function () {
              result.push( a[ i ] );
            },
            greater: function () {
              result.push( b[ j ] );
            },
            result: function () {
              return result.concat( a.slice( i ) );
            }
          }
        }[ operator ];

      return function ( operandA, operandB, compare ) {
        compare = compare || _compare;

        a = [].concat( operandA ).sort( compare );
        b = [].concat( operandB ).sort( compare );

        while ( a[ i ] && b[ j ] ) {
          switch ( compare( a[ i ], b[ j ] ) ) {
            case 0:
              operation.equal();
              i += 1;
              j += 1;
              break;
            case -1:
              operation.lesser();
              i += 1;
              break;
            case 1:
              operation.greater();
              j += 1;
              break;
          }
        }

        return operation.result();
      };
    };

  return {
    /** @summary 共通部分を求める
     * @param {Array} operandA 被演算子 A
     * @param {Array} operandB 被演算子 B
     * @param {Function} compare カスタム比較関数
     * @returns {Array} 演算結果(共通部分)
     */
    intersection: _base( "intersection" ),
    /** @summary 差集合を求める
     * @param {Array} operandA 被演算子 A
     * @param {Array} operandB 被演算子 B
     * @param {Function} compare カスタム比較関数
     * @returns {Array} 演算結果(差集合)
     */
    difference: _base( "difference" ),
    /** @summary 和集合を求める
     * @param {Array} operandA 被演算子 A
     * @param {Array} operandB 被演算子 B
     * @param {Function} compare カスタム比較関数
     * @returns {Array} 演算結果(和集合)
     */
    union: _base( "union" )
  };
}() );