简体   繁体   中英

JavaScript: Compile array of objects based on a different array of objects

I have an array of invoices and I want to compile an ordered list of monthlyIncome based on a value invoiceMonth (eg "February 2014"). The monthlyIncome array has to store the month name and the income for that month, ie

monthlyIncome = [
    { name: 'January 2014', income: 1000}, 
    { name: 'February 2014', income: 1500 } 
    ...
];

Basically what I need is a "deeper" sort of indexOf(val) , that would check if val is in a specified property of any object of monthlyIncome , and then return that index. In this example I use deepIndexOf(value, property) .

for (var i=0; i<invoices.length; i++) {
    var index = monthlyIncome.deepIndexOf(invoices[i].invoiceMonth, 'name');
    if (index > -1) {
        // month already exists in list, so add the total
        monthlyIncome[index].income += invoice.total;
    } else {
        // month doesn't exist, so add it
        monthlyIncome.push({ 
            name: invoices[i].invoiceMonth, 
            income: invoices[i].total 
        });
    }
}

The only problem is that I don't know exactly how I would write deepIndexOf . Also, I suspect there is a better way to do this in JavaScript than the way I've outlined.

You can do the following to return the first index that matches a property value in your array:

Live Demo

function indexByPropertyVal(values, propName, propVal){
    var i = 0, 
        count = values.length; 

    for(; i < count; i++){
        if(values[i][propName] === propVal){
            return i;    
        }
    }
    return -1; 
}

monthlyIncome = [
    { name: 'January 2014', income: 1000}, 
    { name: 'February 2014', income: 1500 }, 
    { name: 'March 2014', income: 1500 } , 
    { name: 'April 2014', income: 1500 } , 
    { name: 'May 2014', income: 1500 }  
];

alert(indexByPropertyVal(monthlyIncome, 'name', 'April 2014'));

alert(indexByPropertyVal(monthlyIncome, 'name', 'June 2014'));

Then just update this line in your code from:

var index = monthlyIncome.deepIndexOf(invoices[i].invoiceMonth, 'name');

to

var index = indexByPropertyVal(monthlyIncome, 'name', invoices[i].invoiceMonth);


You can also augment the prototype of the Array to include the function:

Live Demo

Array.prototype.indexByPropertyVal = function(propName, propVal){
    var i = 0, 
        count = this.length; 

    for(; i < count; i++){
        if(this[i][propName] === propVal){
            return i;    
        }
    }
    return -1; 
};

Then just update this line in your code from:

var index = monthlyIncome.deepIndexOf(invoices[i].invoiceMonth, 'name');

to

var index = monthlyIncome.indexByPropertyVal('name', invoices[i].invoiceMonth);

Your deepIndexOf function can be like:

function deepIndexOf(array, key, value) {
    var obj;
    for (var idx = 0; idx < array.length; idx++) {
        var obj = array[idx];
        if (obj[key] === value) {
            return idx;
        }
    }
    return -1;
}

var monthlyIncome = [{
    name: 'January 2014',
    income: 1000
}, {
    name: 'February 2014',
    income: 1500
}];

console.log(deepIndexOf(monthlyIncome, 'name', 'January 2014'));
console.log(deepIndexOf(monthlyIncome, 'name', 'February 2014'));
console.log(deepIndexOf(monthlyIncome, 'name', 'None 2014'));

Or, the entire code to compile can be like:

function compile(incomeList, invoice) {
    var found = false;
    for (var i = 0; i < incomeList.length && !found; i++) {
        if (incomeList[i].name === invoice.invoiceMonth) {
            incomeList[i].income += invoice.total;
            found = true;
        }
    }
    if (!found) {
        incomeList.push({
            name: invoice.invoiceMonth,
            income: invoice.total
        });
    }

}

compile(monthlyIncome, {
    invoiceMonth: 'January 2014',
    total: 1000
});
compile(monthlyIncome, {
    invoiceMonth: 'March 2014',
    total: 1000
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM