Skip to content

Commit f47acd9

Browse files
committed
Exception counts
1 parent 8107ffc commit f47acd9

8 files changed

+184
-22
lines changed

karma.conf.js

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module.exports = function(config) {
2121
'karma-chrome-launcher'
2222
],
2323

24+
reporters: ['dots'],
25+
2426
singleRun: true,
2527

2628
captureTimeout: 60000

reductio.js

+73-12
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,55 @@ var reductio_count = {
5151

5252
module.exports = reductio_count;
5353
},{}],3:[function(_dereq_,module,exports){
54+
var reductio_exception_count = {
55+
add: function (a, prior) {
56+
var i, curr;
57+
return function (p, v) {
58+
if(prior) prior(p, v);
59+
// Only count++ if the p.values array doesn't contain a(v) or if it's 0.
60+
i = p.bisect(p.values, a(v), 0, p.values.length);
61+
curr = p.values[i];
62+
if((!curr || curr[0] !== a(v)) || curr[1] === 0) {
63+
p.exceptionCount++;
64+
}
65+
return p;
66+
};
67+
},
68+
remove: function (a, prior) {
69+
var i, curr;
70+
return function (p, v) {
71+
if(prior) prior(p, v);
72+
// Only count-- if the p.values array contains a(v) value of 1.
73+
i = p.bisect(p.values, a(v), 0, p.values.length);
74+
curr = p.values[i];
75+
if(curr && curr[0] === a(v) && curr[1] === 1) {
76+
p.exceptionCount--;
77+
}
78+
return p;
79+
};
80+
},
81+
initial: function (prior) {
82+
return function (p) {
83+
p = prior(p);
84+
p.exceptionCount = 0;
85+
return p;
86+
};
87+
}
88+
};
89+
90+
module.exports = reductio_exception_count;
91+
},{}],4:[function(_dereq_,module,exports){
5492
reductio_count = _dereq_('./count.js');
5593
reductio_sum = _dereq_('./sum.js');
5694
reductio_avg = _dereq_('./avg.js');
5795
reductio_value_count = _dereq_('./value-count.js');
96+
reductio_exception_count = _dereq_('./exception-count.js');
5897

5998
function reductio() {
60-
var order, avg, count, sum, unique_accessor, reduceAdd, reduceRemove, reduceInitial;
99+
var order, avg, count, sum, exceptionAccessor, exceptionCount,
100+
reduceAdd, reduceRemove, reduceInitial;
61101

62-
avg = count = sum = unique_accessor = false;
102+
avg = count = sum = unique_accessor = countUniques = false;
63103

64104
reduceAdd = function(p, v) { return p; };
65105
reduceAdd = function(p, v) { return p; };
@@ -100,9 +140,23 @@ function reductio() {
100140
}
101141
}
102142

103-
if(unique_accessor) {
104-
reduceAdd = reductio_value_count.add(unique_accessor, reduceAdd);
105-
reduceRemove = reductio_value_count.remove(unique_accessor, reduceRemove);
143+
// The unique-only reducers come before the value_count reducers. They need to check if
144+
// the value is already in the values array on the group. They should only increment/decrement
145+
// counts if the value not in the array or the count on the value is 0.
146+
if(exceptionCount) {
147+
if(!exceptionAccessor) {
148+
console.error("You must define an .exception(accessor) to use .exceptionCount(true).");
149+
} else {
150+
reduceAdd = reductio_exception_count.add(exceptionAccessor, reduceAdd);
151+
reduceRemove = reductio_exception_count.remove(exceptionAccessor, reduceRemove);
152+
reduceInitial = reductio_exception_count.initial(reduceInitial);
153+
}
154+
}
155+
156+
// Maintain the values array.
157+
if(exceptionAccessor) {
158+
reduceAdd = reductio_value_count.add(exceptionAccessor, reduceAdd);
159+
reduceRemove = reductio_value_count.remove(exceptionAccessor, reduceRemove);
106160
reduceInitial = reductio_value_count.initial(reduceInitial);
107161
}
108162
}
@@ -131,17 +185,23 @@ function reductio() {
131185
return my;
132186
};
133187

134-
my.uniques = function(value) {
135-
if (!arguments.length) return unique_accessor;
136-
unique_accessor = value;
188+
my.exception = function(value) {
189+
if (!arguments.length) return exceptionAccessor;
190+
exceptionAccessor = value;
191+
return my;
192+
};
193+
194+
my.exceptionCount = function(value) {
195+
if (!arguments.length) return exceptionCount;
196+
exceptionCount = value;
137197
return my;
138198
};
139199

140200
return my;
141201
}
142202

143203
module.exports = reductio;
144-
},{"./avg.js":1,"./count.js":2,"./sum.js":4,"./value-count.js":5}],4:[function(_dereq_,module,exports){
204+
},{"./avg.js":1,"./count.js":2,"./exception-count.js":3,"./sum.js":5,"./value-count.js":6}],5:[function(_dereq_,module,exports){
145205
var reductio_sum = {
146206
add: function (a, prior) {
147207
return function (p, v) {
@@ -167,7 +227,7 @@ var reductio_sum = {
167227
};
168228

169229
module.exports = reductio_sum;
170-
},{}],5:[function(_dereq_,module,exports){
230+
},{}],6:[function(_dereq_,module,exports){
171231
// TODO: Figure out how to use a global crossfilter object. We need to
172232
// import here because the testing framework doesn't provide global
173233
// objects. We shouldn't need to require this for use in browser.
@@ -191,6 +251,7 @@ var reductio_value_count = {
191251
};
192252
},
193253
remove: function (a, prior) {
254+
var i;
194255
return function (p, v) {
195256
if(prior) prior(p, v);
196257
i = p.bisect(p.values, a(v), 0, p.values.length);
@@ -211,6 +272,6 @@ var reductio_value_count = {
211272
};
212273

213274
module.exports = reductio_value_count;
214-
},{}]},{},[3])
215-
(3)
275+
},{}]},{},[4])
276+
(4)
216277
});

reductio.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/exception-count.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
var reductio_exception_count = {
2+
add: function (a, prior) {
3+
var i, curr;
4+
return function (p, v) {
5+
if(prior) prior(p, v);
6+
// Only count++ if the p.values array doesn't contain a(v) or if it's 0.
7+
i = p.bisect(p.values, a(v), 0, p.values.length);
8+
curr = p.values[i];
9+
if((!curr || curr[0] !== a(v)) || curr[1] === 0) {
10+
p.exceptionCount++;
11+
}
12+
return p;
13+
};
14+
},
15+
remove: function (a, prior) {
16+
var i, curr;
17+
return function (p, v) {
18+
if(prior) prior(p, v);
19+
// Only count-- if the p.values array contains a(v) value of 1.
20+
i = p.bisect(p.values, a(v), 0, p.values.length);
21+
curr = p.values[i];
22+
if(curr && curr[0] === a(v) && curr[1] === 1) {
23+
p.exceptionCount--;
24+
}
25+
return p;
26+
};
27+
},
28+
initial: function (prior) {
29+
return function (p) {
30+
p = prior(p);
31+
p.exceptionCount = 0;
32+
return p;
33+
};
34+
}
35+
};
36+
37+
module.exports = reductio_exception_count;

src/reductio.js

+30-8
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ reductio_count = require('./count.js');
22
reductio_sum = require('./sum.js');
33
reductio_avg = require('./avg.js');
44
reductio_value_count = require('./value-count.js');
5+
reductio_exception_count = require('./exception-count.js');
56

67
function reductio() {
7-
var order, avg, count, sum, unique_accessor, reduceAdd, reduceRemove, reduceInitial;
8+
var order, avg, count, sum, exceptionAccessor, exceptionCount,
9+
reduceAdd, reduceRemove, reduceInitial;
810

9-
avg = count = sum = unique_accessor = false;
11+
avg = count = sum = unique_accessor = countUniques = false;
1012

1113
reduceAdd = function(p, v) { return p; };
1214
reduceAdd = function(p, v) { return p; };
@@ -47,9 +49,23 @@ function reductio() {
4749
}
4850
}
4951

50-
if(unique_accessor) {
51-
reduceAdd = reductio_value_count.add(unique_accessor, reduceAdd);
52-
reduceRemove = reductio_value_count.remove(unique_accessor, reduceRemove);
52+
// The unique-only reducers come before the value_count reducers. They need to check if
53+
// the value is already in the values array on the group. They should only increment/decrement
54+
// counts if the value not in the array or the count on the value is 0.
55+
if(exceptionCount) {
56+
if(!exceptionAccessor) {
57+
console.error("You must define an .exception(accessor) to use .exceptionCount(true).");
58+
} else {
59+
reduceAdd = reductio_exception_count.add(exceptionAccessor, reduceAdd);
60+
reduceRemove = reductio_exception_count.remove(exceptionAccessor, reduceRemove);
61+
reduceInitial = reductio_exception_count.initial(reduceInitial);
62+
}
63+
}
64+
65+
// Maintain the values array.
66+
if(exceptionAccessor) {
67+
reduceAdd = reductio_value_count.add(exceptionAccessor, reduceAdd);
68+
reduceRemove = reductio_value_count.remove(exceptionAccessor, reduceRemove);
5369
reduceInitial = reductio_value_count.initial(reduceInitial);
5470
}
5571
}
@@ -78,9 +94,15 @@ function reductio() {
7894
return my;
7995
};
8096

81-
my.uniques = function(value) {
82-
if (!arguments.length) return unique_accessor;
83-
unique_accessor = value;
97+
my.exception = function(value) {
98+
if (!arguments.length) return exceptionAccessor;
99+
exceptionAccessor = value;
100+
return my;
101+
};
102+
103+
my.exceptionCount = function(value) {
104+
if (!arguments.length) return exceptionCount;
105+
exceptionCount = value;
84106
return my;
85107
};
86108

src/value-count.js

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var reductio_value_count = {
2121
};
2222
},
2323
remove: function (a, prior) {
24+
var i;
2425
return function (p, v) {
2526
if(prior) prior(p, v);
2627
i = p.bisect(p.values, a(v), 0, p.values.length);

test/exception-count.spec.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Counting tests
2+
describe('Reductio exception count', function () {
3+
var group;
4+
5+
beforeEach(function () {
6+
var data = crossfilter([
7+
{ foo: 'one', bar: 'A' },
8+
{ foo: 'two', bar: 'B' },
9+
{ foo: 'three', bar: 'A' },
10+
{ foo: 'one', bar: 'B' },
11+
{ foo: 'one', bar: 'A' },
12+
{ foo: 'two', bar: 'B' },
13+
]);
14+
15+
var dim = data.dimension(function(d) { return d.foo; });
16+
group = dim.group();
17+
18+
var reducer = reductio()
19+
.exception(function(d) { return d.bar; })
20+
.exceptionCount(true);
21+
22+
reducer(group);
23+
});
24+
25+
it('has three groups', function () {
26+
expect(group.top(Infinity).length).toEqual(3);
27+
});
28+
29+
it('grouping have the right counts', function () {
30+
var values = {};
31+
group.top(Infinity).forEach(function (d) {
32+
values[d.key] = d.value;
33+
});
34+
35+
expect(values['one'].exceptionCount).toEqual(2);
36+
expect(values['two'].exceptionCount).toEqual(1);
37+
expect(values['three'].exceptionCount).toEqual(1);
38+
});
39+
});

test/value-count.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('Reductio value count', function () {
1818
var reducer = reductio()
1919
.sum(function (d) { return d.bar; })
2020
.count(true)
21-
.uniques(function (d) { return d.bar; });
21+
.exception(function (d) { return d.bar; });
2222

2323
reducer(group);
2424
});

0 commit comments

Comments
 (0)