Sort By Multiple Dimensions In Crossfilter.js
Solution 1:
I know it's not using the crossfilter library, but why not use the sort function to do this?
var combos = cf.sort(function(a,b) {
if(a.cat == b.cat) return a.val < b.val ? -1 : 1;
return a.cat < b.cat ? -1 : 1;
});
see http://jsfiddle.net/cQXNK/5/
To allow different dimensions to have different sort directions would just be a matter of swapping -1 for 1 and vice versa
Solution 2:
Using the Array.prototype.sort
, you can:
functionsortByPriority(a, b) {
var p = sortByPriority.properties;
functionpad(str, max) {
str = String(str);
return str.length < max ? pad("0" + str, max) : str;
}
if (!p) {
return a - b;
}
var ar ='', br = '';
for (var i = 0, max = p.length; i < max; i++) {
ar += pad(a[p[i]], 10);
br += pad(b[p[i]], 10);
}
return ar == br ? 0 : ar > br ? 1 : - 1;
}
How to use:
Sorting cat
then val
sortByPriority.properties = ['cat', 'val'];
myArray.sort(sortByPriority);
Result:
- A 1
- A 3
- A 11
- A 11
- B 2
- B 2
- B 5
- B 100
if you want prior val
do:
sortByPriority.properties = ['val', 'cat'];
myArray.sort(sortByPriority);
Result:
- A 1
- B 2
- B 2
- A 3
- B 5
- A 11
- A 11
- B 100
Not a super effective code but, you can improve it.
UPDATE:
You can use the pad
function to get same results using crossfilter, look this jsfiddle.
var combos = cf.dimension(function(d) {
returnpad(d.cat, 10) + '|' + pad(d.val, 10);
});
You also can change the pad size by the same length from the biggest string in your "coll", this will ensure the result ever.
See that optimization: http://jsfiddle.net/gartz/cQXNK/7/
Solution 3:
Here's what I ended up doing:
- I still use string concatenation on a single new dimension, but
I convert the measure to a positive, comparable decimal before turning it into a string, using crossfilter to get the min/max:
var vals = cf.dimension(function(d) { return d.val }), min = vals.bottom(1)[0].val, offset = min < 0 ? Math.abs(min) : 0, max = vals.top(1)[0].val + offset, valAccessor = function(d) { // offset ensures positive numbers, fraction ensures sort order return ((d.val + offset) / max).toFixed(8); }, combos = cf.dimension(function(d) { return d.cat + '|' + valAccessor(d); });
See working fiddle: http://jsfiddle.net/nrabinowitz/cQXNK/9/
This has the advantage of handling negative numbers properly - not possible with zero-padding, as far as I can tell. It seems to be just as fast. The downside is that it requires creating a new dimension on the numeric column, but in my case I usually require that in any case.
Solution 4:
I haven't tested for preformance but you could give d3.nest a go. Example code:
var nested = d3.nest()
.key(function(d) { return d.cat; })
.sortKeys(d3.ascending)
.sortValues(compareValues)
.entries(data);
See the whole fiddle here: http://jsfiddle.net/RFontana/bZX7Q/
And let me know what result you get if you run some jsperf :)
Post a Comment for "Sort By Multiple Dimensions In Crossfilter.js"