Sun Wareechuensuk
Sun Wareechuensuk

Reputation: 93

JS: Aggregate Array of object

I am working on an array of change logs (object)

Each element in my array is one field change of an item. My Array looks like this

changeLogArray=[{"ItemNo":"01", "Field":"Price","OldValue":"100","NewValue":"200","CreatedDate":"17/10/2020"},
{"ItemNo":"01", "Field":"Price","OldValue":"200","NewValue":"300","CreatedDate":"18/10/2020"},
{"ItemNo":"01", "Field":"Price","OldValue":"300","NewValue":"400","CreatedDate":"19/10/2020"},
{"ItemNo":"01", "Field":"Name","OldValue":"A","NewValue":"B","CreatedDate":"19/10/2020"}]

I want to combine the only changes of Field Price into one row my wanted result outcome: Only one row for changes of Field=Price, OldValue of the first record, NewValue of the final record (orderby createdDate)

[{"ItemNo":"01", "Field":"Price","OldValue":"100","NewValue":"400","CreatedDate":"19/10/2020"},
{"ItemNo":"01", "Field":"Name","OldValue":"A","NewValue":"B","CreatedDate":"19/10/2020"}]

This is what I have right now;

                            var lstToDisplayNotSellingPrice = changeLogArray.filter(item => {
                            return item.Field != 'Selling Price'
                        })

                        var lstToDisplaySellingPrice  = changeLogArray.filter(item => {
                            return item.Field == 'Selling Price'
                        })

                        var resultChangeLogSellingPrice = []


                        changeLogArray.forEach((item, index) =>{
                            
                            var distinctItemIndex
                            if(index == 0 || item.ItemNo != lstToDisplaySellingPrice[index-1].ItemNo){
                                resultChangeLogSellingPrice.push(item)
                                distinctItemIndex = index
                            }else{
                                if(item.FieldLevel == lstToDisplaySellingPrice[index-1].ItemNo){
                                    resultChangeLogSellingPrice.pop()
                                    var itemLog = lstToDisplaySellingPrice[index-1]
                                    itemLog.NewValue = item.NewValue
                                    itemLog.CreatedDate = item.CreatedDate
                                    resultChangeLogSellingPrice.push(itemLog)
                                }
                            }

                        });

I tried to seperate the one that Field=Selling Price first, then use that array which contains only Selling Price changes and use forEach on each ItemNo if the current row has the same ItemNo as the previous, pop the previous log and then push new log which has the NewValue and the CreatedDate of the current row. And in the end I will combine list of Price Changes and list of other changes into the result array

Upvotes: 1

Views: 53

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386654

By having an array of sorted items by CreatedDate, you could take an object for grouping with ItemNo and Field.

Then assign an object if novalue exists and update NewValue and CreatedDate.

const
    data = [{ ItemNo: "01", Field: "Price", OldValue: "100", NewValue: "200", CreatedDate: "17/10/2020" }, { ItemNo: "01", Field: "Price", OldValue: "200", NewValue: "300", CreatedDate: "18/10/2020" }, { ItemNo: "01", Field: "Price", OldValue: "300", NewValue: "400", CreatedDate: "19/10/2020" }, { ItemNo: "01", Field: "Name", OldValue: "A", NewValue: "B", CreatedDate: "19/10/2020" }],
    result = Object.values(data.reduce((r, o) => {
        const key = ['ItemNo', 'Field'].map(k => o[k]);
        r[key] ??= { ...o };
        r[key].NewValue = o.NewValue;
        r[key].CreatedDate = o.CreatedDate;
        return r;
    }, { }));
   
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions