Zainul Abideen
Zainul Abideen

Reputation: 1900

Trouble creating array of objects

I have an array and I want to pick 3 of its elements and put store it in another array as a single object and again repeatedly follow the same process on every 3 elements of the array. This is my code below:

let breakpoints = [
  {name: "from-amonut", value: "100"},
  {name: "to-amonut", value: "200"},
  {name: "gst", value: "10"},
  {name: "from-amonut", value: "200"},
  {name: "to-amonut", value: "300"},
  {name: "gst", value: "20"},
  {name: "from-amonut", value: "300"},
  {name: "to-amonut", value: "400"},
  {name: "gst", value: "30"}
];

let temp = {
  "from_amount": 0,
  "to_amount": 0,
  "gst": 0
};

let formattedBreakpoints = [];

breakpoints.map((v, k) => {
  (v.name == "from-amonut") ? temp.from_amount = v.value: "";
  (v.name == "to-amonut") ? temp.to_amount = v.value: "";
  (v.name == "gst") ? temp.gst = v.value: "";
  ((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), console.log(temp)) : "";

});
console.log(formattedBreakpoints);

I'm expecting formattedBreakpoints to be [{"from_amount":100, "to_amount":200, "gst":10}, {"from_amount":200, "to_amount":300, "gst":20}.....] but only returns all the objects with the value of last array elements.

Upvotes: 0

Views: 75

Answers (3)

Eugene Tsakh
Eugene Tsakh

Reputation: 2879

The problem with your code that you are mutating a single object temp and pushing it 3 times to the result array. So what's going on:

  1. You are creating an object
  2. In a map method you are mutating it repeatedly and after every 3 iterations you are setting reference to this object to the result array.

Key word here is reference. That means that this is the same object. For example:

const result = [];
const obj = {};

obj.a = 'a';
result.push(obj); // => result = [{ a: 'a' }]

obj.b = 'b';
result.push(obj); // => result = [{ a: 'a', b: 'b' }, { a: 'a', b: 'b' }]

Try this way:

let formattedBreakpoints = [];
for (let i = 0; i < breakpoints.length; i += 3) {
  const breakPointOptions = breakpoints.slice(i, i + 3);
  formattedBreakpoints.push(breakPointOptions.reduce((result, { name, value }) => {
    result[name] = value;
    return result;
  }, {}));
}

Upvotes: 2

Ori Drori
Ori Drori

Reputation: 191976

You can use Array.reduce() to add all properties to the last object. Whenever the index (i) remainder from 3 is 0, you add another object to the accumulator.

const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];
        
const result = breakpoints.reduce((r, { name, value }, i) => {
  if(i % 3 === 0) r.push({});
  
  const key = name.replace(/-/g, '_');

  r[r.length - 1][key] = value;
  
  return r;
}, []);

console.log(result);

What's the problem in your code is the reuse of temp. Since temp is an object, pushing it to the array, adds the reference to the array, and doesn't create a new object. To prevent that, you can init temp whenever you get to the last property. You should also use Array.forEach() (do something with value) instead of Array.map() (create new array with items based on original values).

const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];

let temp = {};

const formattedBreakpoints = [];

breakpoints.forEach((v, k) => {
  if(v.name == "from-amonut") temp.from_amount = v.value;
  if(v.name == "to-amonut") temp.to_amount = v.value;
  if(v.name == "gst") { // whenever we get to gst, we can push to array, and reset temp
    temp.gst = v.value;
    formattedBreakpoints.push(temp);
    temp = {};
  };
});
console.log(formattedBreakpoints);

Upvotes: 2

pr0p
pr0p

Reputation: 2358

let breakpoints = [
    			{name: "from-amonut", value: "100"},
    			{name: "to-amonut", value: "200"},
    			{name: "gst", value: "10"},
    			{name: "from-amonut", value: "200"},
    			{name: "to-amonut", value: "300"},
    			{name: "gst", value: "20"},
    			{name: "from-amonut", value: "300"},
    			{name: "to-amonut", value: "400"},
    			{name: "gst", value: "30"}
    		]
    		let temp = {
    			"from_amount" : 0,
    			"to_amount" : 0,
    			"gst" : 0
    		};
    		let formattedBreakpoints = [];
    		breakpoints.map((v, k)=>{
    			(v.name == "from-amonut") ? temp.from_amount = v.value : "";
    			(v.name == "to-amonut") ? temp.to_amount = v.value : "";
    			(v.name == "gst") ? temp.gst = v.value : "";
    			((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), temp = {... temp}) : "" ;
    			
    		});
    		console.log(formattedBreakpoints);

As temp is an object you are using it by reference. So you need to create a new object each time you push or else the same object will be referenced. Hence I'm using temp itself to create this new object.

Upvotes: 1

Related Questions