Home Reference Source

src/sort.js

import sequence from './sequence';

/**
 * ソートします。
 *
 * @param {*[]} args - [comp, coll]か[coll]。compが省略された場合は<演算子。
 *
 * @return {iterator} ソートされた集合のイテレーター
 *
 * @example
 * sort(                 [2, 3, 1]);  // [1, 2, 3]のイテレーター
 * sort((x, y) => x > y, [2, 3, 1]);  // [3, 2, 1]のイテレーター
 */
export default function sort(...args) {
  const [comp, coll] = (() => {
    switch (args.length) {
    case 0:
      throw 'Invalid arguments';

    case 1:
      return [(x, y) => x < y, args[0]];

    default:
      return args;
    }
  })();

  const _ = function(xs, l, r) {
    if (l < r) {
      let i = l;
      let j = r;

      let pivot = comp(xs[i], xs[j]) ? xs[j] : xs[i];

      for (;;) {
        while (comp(xs[i], pivot)) {
          i++;
        }
        while (comp(pivot, xs[j])) {
          j--;
        }

        if (i >= j) {
          break;
        }

        const temp = xs[i]; xs[i] = xs[j]; xs[j] = temp;

        i++;
        j--;
      }

      _(xs, l, i - 1);
      _(xs, j + 1, r);
    }
  };

  const xs = Array.from(coll);

  _(xs, 0, xs.length - 1);

  return sequence(xs);
}