遍历一个对象数组并根据条件添加到其他数组

遍历一个对象数组并根据条件添加到其他数组

问题描述:

我有一个包含以下对象的数组。遍历一个对象数组并根据条件添加到其他数组

var notTotal = [{"Year":2012,"Value":800579}, 
       {"Year":2012,"Value":654090}, 
       {"Year":2012,"Value":758092}, 
       {"Year":2013,"Value":343928},...More objects.. ] 

我想要做的是遍历这个对象数组,其中只有一年存在而不是多个,并且将当年的值加起来。用上面的例子..

var total = [{"Year":2012,"Value":2556689}, 
//Total of first three 2012 assuming there isnt anymore 2012 in the array 
      {"Year":2013,"Value":343928},...] 

我已经试过类似如下:

for(var i = 0; i < notTotal.length; i++) { 
    if (total.includes(notTotal[i].Year || notTotal[i])) { 
     //Add the value of the year in notTotal array to the same year in total array 
    } else { 
    total.push(notTotal[i]); //add year and value if it does not exist to the total array 
} 
} 

道歉,如果这是一个重复。这似乎是一个非常具体的问题。

谢谢!

+0

你所需要的最终结果('total')是一个数组?使用将字符映射到值的字典可以非常容易地实现(因为键必须是唯一的)。 – AstroCB

+0

请参阅[这个答案](https://*.com/questions/23521894/how-to-aggregate-objects-properties)。 –

+0

它需要是一个数组,然后将其插入到D3条形图布局中。 – Stu

一个简单的解决方案是创建一个对象,持有总量按年份。

var totalByYear = {}; 

然后,您可以使用循环的notTotal.forEach阵列或for循环,你已经证明,增加了有关今年totalByYear物体内部的价值在。

notTotal.forEach(function(ele) { totalByYear[ele.Year] += ele.Value }); 

这产生具有年份键和总值的对象,例如,使用例如:

{'2012': 2556689, '2013': 343928 /* other years */} 

所述期望的格式(对于D3)然后可以从totalByYear对象(以及由年总计印刷)内置:

var totals = []; 
for (year in totalByYear) { 
    console.log('Total for year ' + year + ' is ' + totalByYear[year]); 
    //Build the correctly formatted array 
    totals.push({ Year: year, Value: totalByYear[year]}); 
} 

//Prints: 
//Total for year 2012 is 2556689 
//etc.etc. 

totals阵列然后将具有所需格式。

+0

很棒的回答。然而,我需要保留[{“Year”:yyyy,“Value”:n} ...]的格式,然后使用它来放入D3.js布局。 – Stu

+0

@sru您可以使用最后一行的psidoms最后一步... –

+0

我已经添加到答案的结尾,显示如何保留'D3.js' –

,你可以建立一个哈希表:

var hash = {},total=[]; 
for(const {Year,Value} of notTotal){ 
    if(hash[Year]){ 
    hash[Year].Value+=Value; 
    }else{ 
    total.push(hash[Year]={Year,Value}); 
    } 
} 

In action

注:对象属性通常不大写...

+0

赞赏。我从D3.json函数加载这些数据,并且这些属性已经大写了。 – Stu

伟大的问题!要解释您的if (total.includes(notTotal[i].Year || notTotal[i]))中发生的情况是,您正在通过total阵列查看一年中的数据,或者仅仅是现有的notTotal[i]。所以你的循环试图找到一个值正好是2012或正好"Year":2012,"Value":2556689。 ERGO,如果你的total数组是这样的:

[{"Year":2012, "Value": 12345}] 

你的循环将找不到它,即使没有与2012为一年的对象。至于如何解决这个问题,请看看前面的问题!

How to determine if Javascript array contains an object with an attribute that equals a given value?

希望帮助:)

+0

的格式,因为年份始终是真的,或是无关紧要的...... –

+0

真的!非常感谢你指出:) –

你可以使用一个哈希表,并检查今年不存在,然后生成一个新的结果集。然后更新总数。

var values = [{ Year: 2012, Value: 800579 }, { Year: 2012, Value: 654090 }, { Year: 2012, Value: 758092 }, { Year: 2013, Value: 343928 }], 
 
    hash = Object.create(null), 
 
    totals = []; 
 
    
 
values.forEach(function (o) { 
 
    hash[o.Year] || totals.push(hash[o.Year] = { Year: o.Year, Value: 0 }); 
 
    hash[o.Year].Value += o.Value; 
 
}); 
 

 
console.log(totals);

var notTotal = [{"Year":2012,"Value":800579}, 
 
       {"Year":2012,"Value":654090}, 
 
       {"Year":2012,"Value":758092}, 
 
       {"Year":2013,"Value":343928}] 
 
       
 
var totalObj = notTotal.reduce((sum, obj) => { 
 
    sum[obj.Year] = sum[obj.Year] + obj.Value || obj.Value; 
 
    return sum; 
 
}, {}); 
 

 
// convert total to the format you need; 
 
var total = Object.entries(totalObj).map(([Year, Value]) => ({Year, Value})) 
 

 
console.log(total);

+0

这相当于sebs的答案,不同之处在于他是第一个,并将努力付诸正确的解释... –

多了一个解决方案:

function yearlyValueFilter(array){ 
    var yearlyValue = {} 
    array.forEach((obj) => { //litterate on the input 
    var year = obj.Year 
    var value = obj.Value 
    if((year in yearlyValue)){ //if the array with not duplicated years conatins the litteration year just plus that value 
     yearlyValue[year] += value 
    }else{  //if not conatins, it gets as a basic value 
     yearlyValue[year] = value 
    } 
    }) 
    return yearlyValue 
} 
+0

这既不是自我解释,也不是可以理解的。 –