-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Sort transform #1609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sort transform #1609
Changes from 3 commits
0be666f
36f7acd
1a21ad9
823375c
2dd1333
9c70ee9
4f91957
4e8efe4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,7 @@ | |
|
||
var Lib = require('../lib'); | ||
var PlotSchema = require('../plot_api/plot_schema'); | ||
var axisIds = require('../plots/cartesian/axis_ids'); | ||
var autoType = require('../plots/cartesian/axis_autotype'); | ||
var setConvert = require('../plots/cartesian/set_convert'); | ||
var Axes = require('../plots/cartesian/axes'); | ||
|
||
exports.moduleType = 'transform'; | ||
|
||
|
@@ -76,13 +74,13 @@ exports.calcTransform = function(gd, trace, opts) { | |
if(!opts.enabled) return; | ||
|
||
var target = opts.target; | ||
var targetArray = getTargetArray(trace, target); | ||
var targetArray = Lib.getTargetArray(trace, target); | ||
var len = targetArray.length; | ||
|
||
if(!len) return; | ||
|
||
var arrayAttrs = PlotSchema.findArrayAttributes(trace); | ||
var d2c = getDataToCoordFunc(gd, trace, target, targetArray); | ||
var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray); | ||
var indices = getIndices(opts, targetArray, d2c); | ||
|
||
for(var i = 0; i < arrayAttrs.length; i++) { | ||
|
@@ -98,59 +96,6 @@ exports.calcTransform = function(gd, trace, opts) { | |
} | ||
}; | ||
|
||
// TODO reuse for filter.js | ||
function getTargetArray(trace, target) { | ||
if(typeof target === 'string' && target) { | ||
var array = Lib.nestedProperty(trace, target).get(); | ||
|
||
return Array.isArray(array) ? array : []; | ||
} | ||
else if(Array.isArray(target)) return target.slice(); | ||
|
||
return false; | ||
} | ||
|
||
// TODO reuse for filter.js | ||
function getDataToCoordFunc(gd, trace, target, targetArray) { | ||
var ax; | ||
|
||
// If target points to an axis, use the type we already have for that | ||
// axis to find the data type. Otherwise use the values to autotype. | ||
if(target === 'x' || target === 'y' || target === 'z') { | ||
ax = axisIds.getFromTrace(gd, trace, target); | ||
} | ||
// In the case of an array target, make a mock data array | ||
// and call supplyDefaults to the data type and | ||
// setup the data-to-calc method. | ||
else if(Array.isArray(target)) { | ||
ax = { | ||
type: autoType(targetArray), | ||
// TODO does this still work with the new hash object | ||
_categories: [] | ||
}; | ||
setConvert(ax); | ||
|
||
// build up ax._categories (usually done during ax.makeCalcdata() | ||
if(ax.type === 'category') { | ||
for(var i = 0; i < targetArray.length; i++) { | ||
ax.d2c(targetArray[i]); | ||
} | ||
} | ||
} | ||
|
||
// if 'target' has corresponding axis | ||
// -> use setConvert method | ||
if(ax) return ax.d2c; | ||
|
||
// special case for 'ids' | ||
// -> cast to String | ||
if(target === 'ids') return function(v) { return String(v); }; | ||
|
||
// otherwise (e.g. numeric-array of 'marker.color' or 'marker.size') | ||
// -> cast to Number | ||
return function(v) { return +v; }; | ||
} | ||
|
||
function getIndices(opts, targetArray, d2c) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Challenge to all plotly.js contributors: find a faster sort algorithm that this O(n^2) attempt. Note that binary search is nice, but doesn't work so great for arrays with duplicate items. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I quite understand. For the overall sort? Can you use something like stable? 1. assemble There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stable sorting may be useful, e.g. the user presorted based on some criteria, we'd keep that, even if this new facility will support sorting based on multiple fields. Stable sorting is simple with the built-in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @monfera , that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ^^ put in a bit more code for copy/paste into console in isolation and fixed a typo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ^^ another fix and using actual objects to verify stability of the sorting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @monfera how does ^^ handle duplicate items? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some interesting results in https://gist.github.com/etpinard/86949a01309d5505fab8ccca2b0cd875 Looks like my dumb attempt isn't that bad after all (barring any typos ...) |
||
var len = targetArray.length; | ||
var indices = new Array(len); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either this should be
: false
or the one below should be[]
I'd probably vote for
false
and then instead of theif(!len) return;
check, doif(!targetArray) return;
That said, this raises the question, in these applications, of what we should do when
targetArray
isn't the same length as the other associated arrays. Looks like for both, it will truncate (or extend) all of them to the length oftargetArray
. Is that what we want? Seems right for sort, but if we agree then lets 🔒 it with a test. For filter there's an argument to be made that eg[]
and)(
, and{}
and}{
, should be complementary - which they are withintargetArray
but not with respect to the items beyond it. Maybe that's still what we want, or maybe we don't want the extra complexity in so far as we think this would be incorrect usage with no legitimate use case. I don't have a strong opinion other than that it should be clear how we handle this case.BTW it took me a minute to recall the motivation for the different cases in this function - can you give the function a docstring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that's how I designed back when
filter
was first added.Sure thing.
good call 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done in 2dd1333 , 9c70ee9 and 4f91957