简体   繁体   中英

Update property of object inside Array

On the click of a button the data in fruitData array gets added to another array called history. I want the property 'bins' inside history to update whenever the properties: "kultivar", "blokNommer" and "year" match with the objects added from fruitData. (number inside bins property needs to be added together if there is a match)

for example this:

[
{datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}, 
{datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}
]

should equal this (bins: 40):

[
 {datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "40", year: "2020"}
]

My code:

 let fruitData = [{ datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020" }, { datum: "2020-09-18", kultivar: "wb", ha: "5", blokNommer: "1", bins: "5", year: "2020" }, { datum: "2020-03-09", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020" }, { datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020" } ] historyButton.addEventListener('click', () => { addToHistory(fruitData) }) function addToHistory(elements) { for (let elem in elements) { history = [...history, elements[elem]]; } sortHistory() } function sortHistory() { let newHistory = []; history.forEach(function(item, index) { if (newHistory.length === 0) { newHistory.push(item) } else { newHistory.forEach(function(itm, idx) { if (item.year === itm.year && item.kultivar === itm.kultivar && item.blokNommer === itm.blokNommer) { item.bins = item.bins + itm.bins } else { newHistory.push(item) } }) } }) console.log(newHistory) }

This does not give the output I am looking for. Have tried reduce method as well with no luck. Would appreciate any help!

The problem with your implementation is that you are changing the itm.bins . Array.forEach creates a copy of each element when you traverse it, so any value you change for itm wouldn't reflect in the actual array. Hence you are provided with the idx if you want to change the actual element.

Also, you are using + for adding strings, not integers. You need to convert it to integers first to get the desired result.

The final code should be:

function sortHistory(){
        let newHistory = [];
        history.forEach(function(item, index){
            if(newHistory.length === 0){
                newHistory.push(item)
            } else{
                newHistory.forEach(function(itm, idx){
                    if(item.year === itm.year && item.kultivar === itm.kultivar && item.blokNommer === 
                       itm.blokNommer){
                        newHistory[idx].bins = parseInt(item.bins) + parseInt(itm.bins);
                    }else{
                        newHistory.push(item)
                    }
                })
            }
        })
        console.log(newHistory);
history = newHistory;}

You need to iterate the original array, and use find() to retrieve the existing item in the history array which match to kultivar , blokNommer and year in order to access bins and update it.

Note : It's also important to convert bins by Number() as its string in your example, and after that convert it back to string .

 const arr = [ {datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}, {datum: "2020-09-18", kultivar: "wb", ha: "5", blokNommer: "1", bins: "5", year: "2020"}, {datum: "2020-03-09", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}, {datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"} ] const history = []; arr.forEach(item => { const found = history.find(({ kultivar, blokNommer, year }) => kultivar === item.kultivar && blokNommer === item.blokNommer && year === item.year) if(found) { found.bins = (Number(found.bins) + Number(item.bins)).toString(); } else { history.push(item); } }); console.log(history);

find() Number()

If your fruitData array not very big you can try use iterating over elements and searching indexOf the entire array cast to a string by JSON.stringify
But if the array is large then the code is not optimal


 const fruitData = [ {datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}, {datum: "2020-09-18", kultivar: "wb", ha: "5", blokNommer: "1", bins: "5", year: "2020"}, {datum: "2020-03-09", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}, {datum: "2020-04-08", kultivar: "bc", ha: "5", blokNommer: "1", bins: "20", year: "2020"}] const sortHistory = (myArray) => Object.keys(myArray).reduce((accum, item) => { const currItem = JSON.stringify(myArray[item]) const allArr = JSON.stringify(accum) return (allArr.indexOf(currItem) >= 0)? accum: accum.concat(myArray[item]) }, []) console.log(sortHistory(fruitData))

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