How can I push a dynamic object into array? [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript expression to define object’s property name?
I'm trying to add objects to an array, but I want to have the name and value to be dynamic. Here's an example:
(function(){
var data = [];
for(i=0; i<5; i++){
data.push({'name' + i: i});
}
console.log(data);
})()
I guess I can't use a variable for the property so I'm not sure what to do.

If you want to use a dynamically named property, you need to use array access notation:
var temp = {};
temp['name' + i] = i;
data.push(temp);
In the IIFE:
(function(){
var data,
temp,
i;
data = [];
for (i = 0; i < 5; i += 1) {
temp = {};
temp['name' + i] = i;
data.push(temp);
}
console.log(data);
}());

Modified code: key based on variable value can be added in an object using '[]'. jsfiddle
(function(){
var data = [], a;
for(i=0; i<5; i++){
a = {};
a['name' + i] = i;
data.push(a);
}
console.log(data);
})()

Like this:
for(i=0; i<5; i++){
var obj = {};
obj["name" + i] = i;
data.push(obj);
}
But I would wonder why you'd want to hard-code the index into the property name.
Since you have an Array, you already have an associated index. It also makes the property hard to look up.
If you need an association of the original index, I'd use a separate property.
for(i=0; i<5; i++){
data.push({name: i, idx: i});
}

Related

JavaScript Object overriding [duplicate]

This question already has answers here:
Push is overwriting previous data in array
(2 answers)
Closed 4 years ago.
For few hours now I been trying to hack this but I really cant seem to succeed. I am trying to create a JSON string as below, but when passing the values of the variable obj to variable j I am getting an array of only the last result of that loop.
instead of getting results such as:
[{machine: "hi"...}
{machine: "2"....}]
I am getting:
[{machine: "2"...}
{machine: "2"....
and keep going with same value}]
What am I doing wrong?
var return_json = function(){
var j = [];
var obj = {};
var td;
for(var i=1;i<tr.length;i++){
td = tr[i].getElementsByTagName("td");
obj['machine'] = td[0].innerHTML;
console.log(obj['machine']);
obj['day'] = td[1].getElementsByTagName("p")[0].innerHTML;
obj['night'] = td[2].getElementsByTagName("p")[0].innerHTML;
j.push(obj);
console.log(j);
}
return j;
};
console.log(save_limitation());
You're only creating a single object instance in obj variable before the loop. In every iteration, you update the properties of the object and push the same object into your array.
To fix it, create a new object within your loop at every iteration.
var return_json = function() {
var j = [];
var td;
for(var i = 1; i < tr.length; i++){
td = tr[i].getElementsByTagName("td");
j.push({
machine: td[0].innerHTML,
day: td[1].getElementsByTagName("p")[0].innerHTML,
night: td[2].getElementsByTagName("p")[0].innerHTML
});
}
return j;
};
Try initalise the td and obj inside the loop for every element:
var return_json = function(){
var j = [];
for(var i=1;i<tr.length;i++){
var obj = {};
var td;
td = tr[i].getElementsByTagName("td");
obj['machine'] = td[0].innerHTML;
console.log(obj['machine']);
obj['day'] = td[1].getElementsByTagName("p")[0].innerHTML;
obj['night'] = td[2].getElementsByTagName("p")[0].innerHTML;
j.push(obj);
console.log(j);
}
return j;
};
console.log(save_limitation());
obj.machine is a reference to td. You need to remove the link to the td once it is assigned. This should solve it.
for(var i=1;i<tr.length;i++){
td = {};
td = tr[i].getElementsByTagName("td");
obj['machine'] = JSON.parse(JSON.stringify(td));
console.log(obj['machine']);
obj['day'] = td[1].getElementsByTagName("p")[0].innerHTML;
obj['night'] = td[2].getElementsByTagName("p")[0].innerHTML;
j.push(obj);
console.log(j);
}
Because obj is defined outside of the loop you are adding the same object to the array each loop. You are updating the properties of obj on every iteration.
Define obj inside of the loop to ensure you are not doing this.
var tr = document.getElementById("myTable").getElementsByTagName("tr");
var return_json = function(){
var j = [];
for(var i=1;i<tr.length;i++){
var obj = {};
var td = tr[i].getElementsByTagName("td");
obj['machine'] = td[0].innerHTML;
obj['day'] = td[1].getElementsByTagName("p")[0].innerHTML;
obj['night'] = td[2].getElementsByTagName("p")[0].innerHTML;
j.push(obj);
}
return j;
};
console.log(return_json());
<table id="myTable">
<tr><td>Machine</td><td>Day</td><td>Night</td></tr>
<tr><td>1</td><td><p>1d</p></td><td><p>1n</p></td></tr>
<tr><td>2</td><td><p>2d</p></td><td><p>2n</p></td></tr>
<tr><td>3</td><td><p>3d</p></td><td><p>3n</p></td></tr>
</table>

Assigning value to function as object property within for loop

I am trying to create an array of objects. One object property is a function, which I want to change value of depending on which number in the array the object is.
When I try to use the 'i' value from the for loop, this is not being maintained in the function as a number. It is remaining a variable.
var array = [];
for (var i = 0; i<number; i++){
array[i].someFunction = function(i) {console.log(i)}}
However, when I call the value held in that property (i.e.):
console.log(array[2].someFunction)
It returns {console.log(i)} instead of {console.log(2)} which is what I want it to do.
Basically you had some problems in your code, like:
not defining number
using var instead of let
not defining the object
using the same value as parameter of the function
here you have the working solution.
var array = [];
// numbers was not defined.
const number = 10;
// use let instead of var
for (let i = 0; i < number; i++) {
// you are not instantiating your object, here is an example.
array[i] = {
"foo": "bar",
"index": i,
}
// you have to change i to j, because if you use i
// it will be the parameter of the function
array[i].someFunction = function(j) {
console.log('index: ', i);
console.log('parameter: ', j)
}
}
// we see the function
console.log(array[2].someFunction)
// we call the function succesfully
array[2].someFunction(100);
It's still referencing i, which has since changed to (number - 1). Save the value somewhere you know it's not subject to change- perhaps in the object itself:
var array = [{}, {}, {}];
for(var i = 0; i < array.length; i++){
array[i].index = i;
array[i].someFunction = function(){console.log(this.index);}
}
//and see that it's working...
for(var i = 0; i < array.length; i++){
array[i].someFunction();
}

Create multiple variables inside for loop

I am trying to create multiple new variables inside a loop.
The number of new variables depends on the lenght of another variable (variable "list" used below).
for(var i = 0; i < list.lenght; i++)
{
var counter + i; // create new variable (i.e. counter1, counter2,...)
}
I found a lot of very simmilar questions on StackOverflow, and the answer is mostly using an array (i.e. How do I create dynamic variable names inside a loop?).
If I use the suggested solution, do I create an array of variables? So in my case I will create multiple counters and I can then add values to that variables, i.e.:
counter6++;
If that is not the case how could I tackle the problem?
I apologize for asking you to explain an old answer, but I cannot comment in the old one because of low reputation.
You have some options here :
Create them global (not best practice ) :
for(var i = 0; i < list.lenght; i++){
window['counter' + i] = 0; // create counter1, counter2,...)
}
Use object :
var scope = {};
for(var i = 0; i < list.lenght; i++){
scope['counter' + i] = 0; // create scope.counter1, scope.counter2,...)
}
Use Object with with keyword
var scope = {};
for(var i = 0; i < list.lenght; i++){
scope['counter' + i] = 0; // create scope.counter1, scope.counter2,...)
}
with(scope){
// here you can acesess keys in the scope object like them variable on the function scope
counter0++
}
Use plain old Array
var scope = new Array(list.length);
You can create an object, set property names to expected variable names, then use object destructuring assignment to get the property assignment or index of an object having a .length as a variable identifier; or use array destructuring to assign an identifier to a specfic index.
let [list, obj] = ["abc", {}];
for (let i = 0; i < list.length; i++) {
obj["counter" + i] = list[i]
}
let {counter0, counter1, counter2} = obj;
console.log(counter0, counter1, counter2);
Alternatively
let list = "abc";
let {0:counter0, 1:counter1, 2:counter2} = list;
console.log(counter0, counter1, counter2);
let list = ["a","b","c"];
let [counter0, counter1, counter2] = list;
console.log(counter0, counter1, counter2);

Loop through and compare javascript objects

I have two arrays which are created from the inputs of a user like so:
var impArray = [];
$('[id^=imp]').on('change', function(){
var value = $(this).val();
var name = ($(this).attr('name').replace('imp-',''))
impArray[name] = value;
console.log(impArray);
})
var assessArray= [];
$('[id^=assess]').on('change', function(){
var value = $(this).val();
var name = ($(this).attr('name').replace('assess-',''))
assessArray[name] = value;
console.log(assessArray);
})
These create arrays like
assessAray
1-1: 10
1-2: 15
1-3: 9
impArray
1-1: 6
1-2: 14
1-3: 2
I then need to do a simple calculation with the matching keys like:
$('#comp-1-1').val(impArray['1-1'] / assessArray['1-1'] * 100);
Obviously I can't do this with every single one, so,
Question: How can I loop through the arrays and compare them based on keys then do something with their values?
Technically, you are working with JavaScript objects, not arrays. Your variable declarations should actually be:
var impArray = {};
var assessArray = {};
Once you have the correct variable declarations, you can use jQuery.each to iterate through keys (not indexes):
$.each(impArray, function(key, value){
$('#comp-'+key).val(assessArray[key]/value*100);
});
Try using $.each(), like:
$.each(impArray, function(i, v){
$('#comp-'+i).val(v/assessArray[i]*100);
});
Does this help you?
$.each(impArray, function(index, value){
var result = assessArray[index] / value * 100;
$('#comp-1-'+index).val(result);
});
If both arrays will always be the same length and have the object property at the same index, this should work:
http://jsfiddle.net/9DBuD/
assessArray = [{'1-1':'10'},{'1-2':'15'},{'1-3':'9'}];
impArray = [{'1-1':'6'},{'1-2':'14'},{'1-3':'2'}];
for(var i=0;i<assessArray.length;i++){
for(var prop in assessArray[i]){
for(var property in impArray[i]){
if(prop == property){
$('#comp-'+prop).val(impArray[i][property]/assessArray[i][prop]*100)
}
}
}
}
Edit
This modified fiddle and code should produce the same results even if the array indexes and sizes do not match:
http://jsfiddle.net/9DBuD/1/
Array.prototype.indexOfProp = function (property) {
for (var i = 0, len = this.length; i < len; i++) {
if (this[i][property]!=undefined) return i;
}
return -1;
}
assessArray = [{'1-2':'15'},{'1-3':'9'},{'1-1':'10'},{'1-4':'10'}];
impArray = [{'1-1':'6'},{'1-3':'2'},{'1-2':'14'}];
for(var i=0;i<assessArray.length;i++){
for(var prop in assessArray[i]){
var index = impArray.indexOfProp(prop)
if(index!=-1){
$('#comp-'+prop).val(impArray[index][prop]/assessArray[i][prop]*100)
}
}
}

how would I go about accessing a deep value using a single variable in bracket notation?

I am wondering how to do the following- I have the following data:
dta = {
"fielddata": {
"text1": "4B030C2E-3D53-4DF8-A3535EF377B45DE5",
"text2": "Unlabeled"
}
}
Which I can access using bracket notation like so
var result = dta["fielddata"]["text1"];
no problem there, And I can use variables like so
var val1 = "fielddata",
val2 = "text1",
acc = dta[val1][val2];
log(acc);
again, terrific- but how about when I only have a single variable holding the dot notation?
like, what if I only have
var val = "fielddata.text1",
acc = dta[val];
log(acc);
This would yield an undefined.
Any thoughts on how to go about this?
Thanks alot!
Marco
var val = "fielddata.text1",
acc = dta, // reference the base object
parts = val.split('.'), // split the val into an Array of individual parts
i;
// Iterate the parts, updating acc each time
for( i = 0; i < parts.length; i++ )
acc = acc[parts[i]];
Another option is JSONPath. For relatively simple usecases, doing it manually is likely a better solution, but with greater complexity, I might use something more formalized.
And while I hate to suggest it, there's always eval('dta.fielddata.text1')
getter
exports.getDeep = function(field, object){
var parts = field.split('.');
var value = object;
// Iterate the parts, updating value each time
for( var i = 0; i < parts.length; i++ ){
value = value[parts[i]];
if(i==parts.length-1){
return JSON.parse(JSON.stringify(value))
}
}
}
setter
exports.setDeep = function(field, object, newvalue){
var parts = field.split('.');
for( var i = 0; i < parts.length; i++ ){
if(i==parts.length-1){
object[parts[i]] = newvalue
return object
}
}
}

Categories