Javascript: In a loop, modify property of object then push to array - javascript

I have the following code (which works correctly):
var arr = [];
for(var i = 0; i < 2; i++) {
var obj = { a: 'A'};
obj.c = 'C' + i;
arr.push(obj);
}
// now arr is:
// [ {a: 'A', 'c': 'C0'}, {a: 'A', 'c': 'C1'} ]
To improve the performance of my code, I placed the obj outside the loop, then adding/modifying the new property only, like this:
var arr = [];
var obj = { a: 'A'};
for(var i = 0; i < 2; i++) {
obj.c = 'C' + i;
arr.push(obj);
}
// now arr is:
// [ {a: 'A', 'c': 'C1'}, {a: 'A', 'c': 'C1'} ]
Why both objects got C1 ? Please explain what I'm doing wrong, and how to place the object out of the loop and get correct results?
Note: I know this is a simple problem where performance is not an issue, but I'm actually dealing with big number of objects in reality where performance matters.

You are pushing the object (not a copy of the object) to the array, and then changing it.
If you want different objects in each index, then you need to create a new object each time you go around the loop.

Like the others wrote, you are changing the same object (the original) all the time which ends in the results being the same (the original).
To place the object out of the loop and still get the correct result, you would still have to 'copy' it inside of the loop:
var arr = [];
var obj = { a: 'A'};
var objstring = JSON.stringify(obj);
for(var i = 0; i < 2; i++) {
var obj = JSON.parse(objstring);
obj.c = 'C' + i;
arr.push(obj);
}

Related

How to add object inside array without reference

My code is so far
var chartSeriesArray = [{"EnableAnimation": true,"AnimationDuration": 1}];
let refArray = chartSeriesArray;
let clonedArray = [...chartSeriesArray]; // will clone the array
var x = [];
for(i=0;i<2;i++){
x.push(clonedArray);
}
x[0].foo = "bar";
console.log(x);
Console Output is
0:[{…}, foo: "bar"]
1:[{…}, foo: "bar"]
Whether I am trying to loop refArray or clonedArray in both the cases, it's added foo in both item 0 and 1, i want to add only in 0 for example.
Expected output is
0:[{…}, foo: "bar"]
1:[{…}]
I want to access 0 and 1 individually later.
I tried everything but nothing works, Any help is highly appreciated.
Further after all suggestions, when i am trying below code
var metadata =
{
"KPISDetail": [{
"ChartSeriesList": {
"EnableAnimation": true,
"AnimationDuration": 1
}
}, {
"ChartSeriesList": {
"EnableAnimation": true,
"AnimationDuration": 1
}
}]
}
var data = [];
var x = [];
for(var l=0;l<2;l++){
data.push(metadata.KPISDetail[l].ChartSeriesList);
x.push(...data.map(o => Object.assign({}, o)))
}
x[0].foo = "bar";
x[1].foo = "foo";
console.log(x);
Result should be 2 only because my loop is executing 2 times. But i am getting output 3 times, which is wrong. I am getting below output
You are pushing clonedArray into x 2 time but you forgot about both time you are using same variable so memory allocation of both are same so if you want to add something on x element they reflect on both. To achieve desire result that you can use like that -
var chartSeriesArray = [{"EnableAnimation": true,"AnimationDuration": 1}];
let refArray = chartSeriesArray;
let clonedArray = [...chartSeriesArray]; // will clone the array
var x = [];
for(i=0;i<2;i++){
x.push(JSON.parse(JSON.stringify(clonedArray))); // will create magic
}
x[0].foo = "bar";
console.log(x);
Updated Code -
var metadata =
{
"KPISDetail": [{
"ChartSeriesList": {
"EnableAnimation": true,
"AnimationDuration": 1
}
}, {
"ChartSeriesList": {
"EnableAnimation": true,
"AnimationDuration": 1
}
}]
}
var data = [];
var x = [];
for(var l=0;l<2;l++){
x.push(JSON.parse(JSON.stringify(metadata.KPISDetail[1].ChartSeriesList)))
}
x[0].foo = "bar";
x[1].foo = "foo";
console.log(x);
You should create array clone with cloned elements:
let clonedArray = chartSeriesArray.map((item) => Object.assign({}, item))
You can try with the following:
var x = [];
for(i=0;i<2;i++){
let real_clone = clonedArray.slice(0); // if you need to clone an array
let real_clone = JSON.parse(JSON.stringify(clonedArray)); // if you need to clone both array and object
x.push(real_clone);
}
Issue is you create a single cloned array and pushed in multiple time. You need to create a new cloned array for every single push.
var chartSeriesArray = [{"EnableAnimation":true,"AnimationDuration": 1}];
var x = [];
for(i=0;i<2;i++){
x.push([...chartSeriesArray]);
}
x[0].foo = "bar";
console.log(x);

Combining 2 similar JSON

My aim is to combine 2 similar JSON objects so that the output will have its value taken from the json objects supplied. For eg:
var obj1 = {'name': 'xyz', 'age':''}, obj2 = {'name':'', 'age':'66'}
//would like to have some functionality like below that gives me the output
obj3 = combine(obj1,obj2)
//desired output below.
obj3 = {'name': 'xyz', 'age':'66'}
Since you say the two objects are similar I am going to assume that this means for those keys which are common among the two objects one has data and other has ''.
The second assumption I am going to make is that for any keys not common to both the objects you want it to be copied as is to the new object.
var obj1 = {'a': 'b', 'c': ''};
var obj2 = {'a': '', 'c': 'd', 'e': 'f'};
var obj3 = {};
var key;
for (key in obj1) {
if(obj1[key] === '') {
obj3[key] = obj2[key];
} else {
obj3[key] = obj1[key];
}
}
for(key in obj2) {
if(!(key in obj3)) {
obj3[key] = obj2[key];
}
}
Since you added the jQuery tag, I assume you are using it. If so, you can use jQuery's $.extend method.
var obj1 = {'name': 'xyz', 'age':''},
obj2 = {'name':'', 'age':'66'},
obj3 = $.extend(obj1,obj2);
I'm not entirely sure about what the disired result is, but this code should point you in the right direction. It copies values from obj2 to obj1, if the value has a value (with isnt empty or false):
combine = function(a, b) {
var bKeys = Object.keys(b)
for (var i = 0; i < bKeys.length; i++) {
var key = bKeys[i]
if (b[key]) {
a[key] = b[key]
}
}
}

javascript construct an object from an array of strings

I have the following array
var testArray = ["test1", "test2", "test3"];
and an obj which has other object in it
var obj.test1.test2.test3 = "test";
I want to foreach the testArray
and get the following
obj[testArray[0]][testArray[1]][testArray[2]]
or obj["test1"]["test2"]["test3"]
which is equal to obj.test1.test2.test3 and will return "test"
As you stated you are aware, we can take advantage of the obj["test1"] notation to nest ourselves deeper into the target object. In this case, on each iteration we re-assign the "top" of what we are pointing to to be the child of the last iteration.
var obj = { test1: { test2: {test3: 'test' }}};
var current = obj;
var arr = ['test1', 'test2', 'test3'];
for(var i = 0; i < arr.length; i++){
if(current === undefined){ break; }
current = current[arr[i]];
}
console.log(current);
How about this:
var testArray = ["test1", "test2", "test3"];
var value = [obj].concat(testArray).reduce(function(prev, curr) {
return prev[curr];
});
But remember that reduce is not supported by IE <= 8 (Reduce reference).
function extractDeep(obj, propPathArr) {
var prop = obj;
propPathArr.forEach(function (item) {
prop = prop[item];
});
return prop;
}
call like:
alert(extractDeep({a: {b: {c: "The property!"}}}, ['a', 'b', 'c']));
NOTE:
You really should add some error checking.
forEach does not work in all browsers
jsFiddle can be found here

How to use hashmap in javascript

I have a hash map I want to use it in javascript. So I thought of converting it into javascript map..how to use it or to do?
Turn it into an object literal...
var map = {
'a' : 'a',
'b': 'b'
...
};
Or use Associative Arrays, for example:
var arr = new Array();
arr["One"] = 1;
arr["Two"] = 2;
arr["Thr"] = 3;
arr["For"] = 4;
for(var i in arr)
{
alert('Key='+i + ', Value = '+arr[i]);
}

Best way to query back unique attribute values in a javascript array of objects?

What would be the best (or fastest) way to find all the possible values of "foo" in the following example array.
var table = [
{foo: 0, bar:"htns", stuff:123},
{foo: 2, bar:"snhn", stuff:156},
{foo: 5, bar:"trltw", stuff:45},
{foo: 5, bar:"lrctm", stuff:564},
//few thousand lines later
{foo: 2596, bar:"cns", stuff:321},
{foo: 2597, bar:"gcrl", stuff:741}
];
Loop through the array and put the values in a hash (object). It is a O(n) algorithm.
var result = {};
for(var i=0; i<table.length; i++) {
result[table[i].foo] = 1; //the value can be anything
}
//now read back the unique values
for (i in result) {
if (result.hasOwnProperty(i)) {
console.log(i);
}
}
This is a typesafe version of Chetan's answer:
var result = {};
for(var i = 0; i < table.length; ++i) {
var value = table[i].foo;
result[(typeof value) + ' ' + value] = value;
}
for(id in result) {
if(result.hasOwnProperty(id)) {
console.log(result[id]);
}
}
It will still break for objects, though: as long as the toString() method hasn't been overwritten, they all share the string representation '[object Object]'.

Categories

Resources