wmakeev
3/24/2015 - 2:42 PM

group_by.clj

var groupBy = function() {
  var GroupBy = function(f, rf) {
    this.f = f;
    this.rf = rf;
    this.grouppedValue = {};
  };

  GroupBy.prototype.init = function() {
    return this.rf.init();
  };

  GroupBy.prototype.result = function(result) {
    return this.rf.result(this.rf.step(result, this.grouppedValue));
  };

  GroupBy.prototype.step = function(result, input) {
    var key = this.f(input);
    this.grouppedValue[key] = this.grouppedValue[key] || [];
    this.grouppedValue[key].push(input);
    return result;
  };

  return function(f) {
    return function(rf) {
      return new GroupBy(f, rf);
    };
  };
}();

var t = require ('transducers-js');
var comp = t.comp, map = t.map, filter = t.filter, mapcat = t.mapcat, transduce = t.transduce;

var append = function(accumulator, element) {
  accumulator.push(element);
  return accumulator;
};

var xform = comp(
  map((x) => { return x + 1; }), 
  filter((x) => { return x < 7; }), 
  groupBy((x) => { return x % 2; }), 
  mapcat((x) => { return x; }));
  
transduce(xform, append, [], [1, 2, 3, 4, 5, 6, 7, 8, 9]);

=> [ [ '0', [ 2, 4, 6 ] ], [ '1', [ 3, 5 ] ] ]
(defn group-by [f]
  (fn [rf]
    (let [groupped-value (volatile! (transient {}))]
      (fn
        ([] (rf))
        ([result]
          (rf (rf result (persistent! @groupped-value))))
        ([result input]
          (let [key (f input)]
            (vswap! groupped-value assoc! key (conj (get @groupped-value key []) input))
            result))))))


(def coll (range 1 10))
(def xform (comp (map inc) (filter #(< % 7)) (group-by #(rem % 2)) (mapcat seq)))

(transduce xform conj [] coll)
=> [[0 [2 4 6]] [1 [3 5]]]