2013-01-08 44 views
1

我有一个包含像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,但是我无法把头围绕在这个结构上。

回答

3
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,console

+0

对不起,如果这有点不清楚:'[199x,1234]'是指'[year,value]'。您的代码包含计算的最小/最大值中的年份。我编辑张贴澄清这一点。 –

+0

太棒了,这个工程。谢谢!然而,IIUC它需要每个道具上的呼叫(因此每个道具需要一个地图和一个过滤器)。我想没有(合理)的方法来做到这一点只有一个地图/过滤器? –

+0

嘿dev-null ...在漂亮的版本。而不是'arr = arr.concat.apply(arr,value [prop] [1]);',为什么不只是'arr = arr.concat(value [prop] [1]);'? – AndyPerlitch

0

您可以使用JavaScript的Math.maxMath.min函数与apply来获取数组的最大值和最小值。为了让我使用reduce和concating每个记录

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) 
+1

'allValues( '收入')'返回:'[[1,2,3,4],[5,6,7,8]]''未[1,2,3 ,4,5,6,7,8]' – andlrc