1

My code:

export default {
  data() {
    return {
      services: [],
      mydata: [
        {id: 1, count: 102, price: 0.1},
        {id: 1, count: 0, price: 0.09},
        {id: 2, count: 20, price: 0.5},
      ]
    };
  },
  mounted() {
    this.start();
  },
  methods: {
    start() {
      this.services = this.mydata.reduce((acc, curr) => {
        let item = acc.find((obj) => obj.id == curr.id);
        if (item) {
          item.count += curr.count;
          item.price = item.price > curr.price ? curr.price : item.price;
        } else {
          acc.push(curr);
        }
        return acc;
      }, []);
    },
  },
};

I want merge the mydata array and save into a services variable. I want that the counts to be sum and the lower price to be selected for the new object. (I used reduce for doing this)

My expected services:

[
        {id: 1, count: 102, price: 0.09},
        {id: 2, count: 20, price: 0.5},
]

It's works but the source data (which is mydata) manipulated and converted to this: (the first object's price manipulated and converted to 0.09 which it was 0.1 before)

[
        {id: 1, count: 102, price: 0.09},
        {id: 1, count: 0, price: 0.09},
        {id: 2, count: 20, price: 0.5}
]

Why does this happen?

2
  • Remove the observable attached to mydata: JSON.parse(JSON.stringify(this.mydata)).reduce... Commented Aug 24, 2020 at 19:54
  • @Ohgodwhy Thanks it worked. Commented Aug 24, 2020 at 20:18

1 Answer 1

1

What happens?

You're actually modyfying mydata.

It happens when you find object in the array:

let item = acc.find((obj) => obj.id == curr.id);

and then modify it

item.count += curr.count;
item.price = item.price > curr.price ? curr.price : item.price;

Why it happens?

In JavaScript we have two types od data types.

  • Primitive types (Boolean, String, Number, null, undefined) and they are passed by value.
  • Array, Function and Object which are are passed by reference

In your case you're finding some object in the array and then modify its properties which means you're operating on the reference.

How to do it?

  1. If you have array of primitive types you can make shallow copy using for example spread operator:
let arr = ['a', 'b', 'c']
[...arr].reduce()
  1. If you have array of complex types you need to write custom fuction or use some library which implements it for you like Lodash or Ramda
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I used JSON.parse(JSON.stringify(this.mydata)).reduce... and it worked. Does it have an equivalent in Lodash?
@FredII Have in mind that using JSON.parse method will lose information about some data. If your objects contain undefined, NaN, Infinity or functions all of them will be replaced with null. Lodash has _.cloneDeep function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.