如何在嵌套对象数组中查找范围

How to find the extents in an array of nested objects?

本文关键字:查找 范围 数组 对象 嵌套      更新时间:2023-09-26

我有一个嵌套对象数组,其中包含每个州每年的GDP、收入、人口等值:

// The "records" array looks like this:
[
    {
        name : "...",
        income : [
            [1995, 1234], // [year, value]
            [1996. 1235],
            [...]
        ],
        GDP : [
            [1995, 1234],
            [1996. 1235],
            [...]
        ],
        population : [
            [1995, 1234],
            [1996. 1235],
            [...]
        ]
    }, {
        name : "...",
        income : [
            [...]
        ],
        GDP : [
            [...]
        ],
        population : [
            [...]
        ]
    }, {
        ...
    }
]

现在,我想找到所有状态和年份中每个维度的最小值和最大值。

populationExtents = [659651, 82536680];
gdpExtents        = [14250, 2498800];
incomeExtents     = [..., ...];

如何在不必多次遍历整个数组的情况下完成此操作?目前,我正在为每个维度做这件事:

var income = records.map(function(d, i) {
    return d.income;
});
var min = d3.min(income, function(d, i) {
    return d3.min(d, function(e) {
            return e[1]; // returns values of each year
        });
});
var max = d3.max(income, function(d, i) {
    return d3.max(d, function(e) {
            return e[1];
        });
});

但我认为这太复杂了,因为我应该能够计算每个维度和状态的所有"局部"最小值,然后一次性计算所有状态的全局最小值(而不是每个维度一次(。

我尝试了几个级别的d3.map和嵌套的d3.min,但无法理解这个结构。

function getMaxMin( prop ) {
    var concat = [].concat,
        arr = concat.apply([], records.map(function(value) {
            return concat.apply([], value[prop]);
        }));
    return [ Math.min.apply(Math.min, arr), Math.max.apply(Math.max, arr) ];
}

或者更漂亮一点:

function getMaxMin( prop ) {
    var arr = [];
    records.map(function(value) {
        arr = arr.concat.apply(arr, value[prop][1]);
    });
    return [ Math.min.apply(Math.min, arr), Math.max.apply(Math.max, arr) ];
}

编辑:排除年份[year, value]并将几乎所有内容置于同一循环下:

function getMaxMin() {
    var arrs = [];
    records.map(function(value) {
        arrs[0] = arrs[0].concat(value.income);
        arrs[1] = arrs[1].concat(value.GDP);
        arrs[2] = arrs[2].concat(value.population);
    });
    arrs[0] = arrs[0].filter(c);
    arrs[1] = arrs[1].filter(c);
    arrs[2] = arrs[2].filter(c);
    function c(value, key) {
        return key % 2;
    }
    return [
        [ Math.min.apply(Math.min, arrs[0]), Math.max.apply(Math.max, arrs[0]) ],
        [ Math.min.apply(Math.min, arrs[1]), Math.max.apply(Math.max, arrs[1]) ],
        [ Math.min.apply(Math.min, arrs[2]), Math.max.apply(Math.max, arrs[2]) ]
    ];
}
var maxMin = getMaxMin();
maxMin === [
    [income-min, income-max],
    [GDP-min, GDP-max],
    [population-min, population-max]
]

演示:http://jsbin.com/ecineg/1/embed?javascript,控制台

您可以将JavaScript的Math.maxMath.min函数与apply一起使用,以获取数组的最大值和最小值。为了获得数组,我使用reduce并连接每个记录的属性

var allValues = function (property) {
  return records.reduce(function (memo, record) {
    return memo.concat(record[property])
  }, [])
}
var allIncome = allValues('income')
Math.max.apply(null, allIncome)
Math.min.apply(null, allIncome)