问题
I have the following data, an array of objects:
var data = [
{ x: 0, y0: 0, y: 100 },
{ x: 1, y0: 0, y: 150 },
{ x: 2, y0: 50, y: 100 },
{ x: 3, y0: 50, y: 150 }
]
I'd like to find the object with the biggest discrepancy between y and y0, using D3.
I can do this to get the biggest difference:
var max_val = d3.max(data, function(d) { return d.y - d.y0;} );
It returns 150. But what I don't know how to do is get the containing object, and learn that the corresponding value of x is 1.
Any ideas?
回答1:
Your question asks how to use d3.max to find this object, but an alternate idea is to use the Javascript Array's sort function to do this for you:
>>> data.sort(function(a, b){ return (b.y - b.y0) - (a.y - a.y0); } )[0]
Object {x: 1, y0: 0, y: 150}
Here I am sorting data using a function that, given two objects a and b, compares them using the difference of their y and y0 properties. By subtracting the value of a from b, I'm returning the objects in descending order and then taking the first Object.
回答2:
I believe currently there isn't a good way of doing this through purely d3. From the d3 docs it states:
Returns the maximum value in the given array using natural order. If the array is empty, returns undefined. An optional accessor function may be specified, which is equivalent to calling array.map(accessor) before computing the maximum value.
I went into the source code to look at how d3.max is calculated:
d3.max = function(array, f) {
var i = -1, n = array.length, a, b;
if (arguments.length === 1) {
while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
while (++i < n) if ((b = array[i]) != null && b > a) a = b;
} else {
while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
}
return a;
}
This is partly due to the fact that your accessor function returns a value itself. You can probably customize it to make it return an object, but d3.max specifically handles numbers.
As other people have stated, there are other ways of handling this with pure Javascript.
Related questions: Why is domain not using d3.max(data) in D3?
回答3:
You can also use the standard array.reduce function to find this without using d3 :
var highestDiscrepencyObject = data.reduce(function(memo, val){
var dis = val.y - val.y0,
memoDis = memo.y - memo.y0;
return (dis > memoDis || memo.y === undefined) ? val : memo;
}, {});
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
来源:https://stackoverflow.com/questions/19303888/d3-use-d3-max-to-get-containing-object