web-dev-qa-db-fra.com

Comment trouver le max/min d'un tableau imbriqué en javascript?

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
30
nachocab

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);
});
74
mbostock

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.

4
kbec

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;
}
2
Rick

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));
2
kennebec

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)).

0
btown