How to find the max/min of a nested array in javascript?

前端 未结 6 1582
情歌与酒
情歌与酒 2020-12-08 01:04

I want to find the maximum of a nested array, something like this:

a = [[1,2],[20,3]]
d3.max(d3.max(a)) // 20

but my array contains a text

相关标签:
6条回答
  • 2020-12-08 01:11

    d3.array provides d3.merge which flattens an array of arrays.

    Coupled with d3.max and javascript's Number as an accessor:

    var max = d3.max(d3.merge(arrays), Number);
    

    For example:

    var input = [["yz", 1, 2], ["xy", 20, 3]];
    
    var max = d3.max(d3.merge(input), Number);
    
    console.log(max);
    <script src="https://d3js.org/d3-array.v2.min.js"></script>

    0 讨论(0)
  • 2020-12-08 01:23

    Use this:

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

    or better:

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

    See MDN for Array.filter method details.

    0 讨论(0)
  • 2020-12-08 01:24

    If you now exactly what columns you want to test, you can use:

    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;
    }
    
    0 讨论(0)
  • 2020-12-08 01:28

    If you have a nested array of numbers (arrays = [[1, 2], [20, 3]]), nest d3.max:

    var max = d3.max(arrays, function(array) {
      return d3.max(array);
    });
    

    Or equivalently, use array.map:

    var max = d3.max(arrays.map(function(array) {
      return d3.max(array);
    }));
    

    If you want to ignore string values, you can use array.filter to ignore strings:

    var max = d3.max(arrays, function(array) {
      return d3.max(array.filter(function(value) {
        return typeof value === "number";
      }));
    });
    

    Alternatively, if you know the string is always in the first position, you could use array.slice which is a bit more efficient:

    var max = d3.max(arrays, function(array) {
      return d3.max(array.slice(1));
    });
    

    Yet another option is to use an accessor function which returns NaN for values that are not numbers. This will cause d3.max to ignore those values. Conveniently, JavaScript's built-in Number function does exactly this, so you can say:

    var max = d3.max(arrays, function(array) {
      return d3.max(array, Number);
    });
    
    0 讨论(0)
  • 2020-12-08 01:32

    It's a cruel hack, but looking at the source code for d3.max, your best bet might be to define a d3.max1 that discards the first element by copying that code, but replacing i=-1 with i=0. The code at that link is excerpted here. Note that I'm not a regular d3.js user, but from what I know of the library, you're going to want make sure your version has an f.call case like this function does, so that it can respond to live updates correctly.

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

    Then it would just be d3.max(d3.max1(a)).

    0 讨论(0)
  • 2020-12-08 01:36

    You can flatten an array and apply a function to each member

    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));
    
    0 讨论(0)
提交回复
热议问题