Je veux trouver le maximum d'un tableau imbriqué, quelque chose comme ceci:
a = [[1,2],[20,3]]
d3.max(d3.max(a)) // 20
mais mon tableau contient un champ de texte que je veux ignorer:
a = [["yz",1,2],["xy",20,3]]
d3.max(a) // 20
Si vous avez un tableau imbriqué de nombres (arrays = [[1, 2], [20, 3]]
), imbriquez d3.max :
var max = d3.max(arrays, function(array) {
return d3.max(array);
});
Ou équivalent, utilisez array.map :
var max = d3.max(arrays.map(function(array) {
return d3.max(array);
}));
Si vous souhaitez ignorer les valeurs de chaîne, vous pouvez utiliser array.filter pour ignorer les chaînes:
var max = d3.max(arrays, function(array) {
return d3.max(array.filter(function(value) {
return typeof value === "number";
}));
});
Sinon, si vous savez que la chaîne est toujours à la première position, vous pouvez utiliser array.slice qui est un peu plus efficace:
var max = d3.max(arrays, function(array) {
return d3.max(array.slice(1));
});
Une autre option consiste à utiliser une fonction d’accesseur qui renvoie NaN
pour des valeurs qui ne sont pas des nombres. Cela fera que d3.max ignorera ces valeurs. De manière pratique, la fonction Number
intégrée de JavaScript remplit exactement cette fonction, vous pouvez donc dire:
var max = d3.max(arrays, function(array) {
return d3.max(array, Number);
});
Utilisez ceci:
function arrmax(arrs) {
var toplevel = [];
var f = function(v) {
return !isNaN(v);
};
for (var i = 0, l = arrs.length; i<l; i++) {
toplevel.Push(Math.max.apply(window, arrs[i].filter(f)));
}
return Math.max.apply(window, toplevel);
}
ou mieux:
function arrmax(arrs) {
if (!arrs || !arrs.length) return undefined;
var max = Math.max.apply(window, arrs[0]), m,
f = function(v){ return !isNaN(v); };
for (var i = 1, l = arrs.length; i<l; i++) {
if ((m = Math.max.apply(window, arrs[i].filter(f)))>max) max=m;
}
return max;
}
Voir MDN pour plus de détails sur la méthode Array.filter.
Si vous voulez maintenant exactement quelles colonnes vous voulez tester, vous pouvez utiliser:
var columns = ["ColumnA", "ColumnB", "ColumnC"];
var max = selectedMax(columns,dataset);
var min = selectedMin(columns,dataset)
function selectedMax(columns, dataset) {
var max;
columns.forEach(function(element, index, array) {
var tmpmax = d3.max(dataset, function(d) {
return +d[element];
});
max = (tmpmax > max || max === undefined) ? tmpmax : max;
});
return max;
}
function selectedMin(columns, dataset) {
var min;
columns.forEach(function(element, index, array) {
var tmpmin = d3.min(dataset, function(d) {
return +d[element];
});
min = (tmpmin < min || min === undefined) ? tmpmin : min;
});
return min;
}
Vous pouvez aplatir un tableau et appliquer une fonction à chaque membre
Array.prototype.flatten= function(fun){
if(typeof fun!= 'function') fun= '';
var A= [], L= this.length, itm;
for(var i= 0; i<L; i++){
itm= this[i];
if(itm!= undefined){
if(!itm.flatten){
if(fun) itm= fun(itm);
if(itm) A.Push(itm);
}
else A= A.concat(itm.flatten(fun));
}
}
return A;
}
var a= [["yz", 1, 2], ["xy", 20, 3]], max=-Infinity;
var max=Math.max.apply(a, a.flatten(Number));
C'est un bidouillage cruel, mais si vous regardez le code source pour d3.max
, votre meilleur choix pourrait être de définir un d3.max1
qui rejette le premier élément en copiant ce code, mais en remplaçant i=-1
par i=0
. Le code sur ce lien est extrait ici. Notez que je ne suis pas un utilisateur régulier de d3.js, mais d'après ce que je sais de la bibliothèque, vous devez vous assurer que votre version dispose d'un cas f.call
comme le fait cette fonction, afin de pouvoir répondre correctement aux mises à jour en direct. .
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;
};
Alors ce serait juste d3.max(d3.max1(a))
.