How to loop over an array of objects using javascript? - javascript

I'm trying to loop an array that contains objects and I keep getting and error: "Cannot set property 'color' of undefined". What am I doing wrong?
var ObjectTest = function(something1, something2){
this.Name = something1;
this.Job = something2;
this.color = '';
this.numbers = [];
}
var first = new ObjectTest('Paul', 'teacher');
var second = new ObjectTest('Jane', 'doctor');
var third = new ObjectTest('Mike', 'student');
var someArray = [];
someArray.push(first, second, third);
console.log(someArray);
for(var i =0; i <= someArray.length; i++){
someArray[i].color = 'red';
};

You need to iterate until the length of the array but not over, because indices are zero based
for (var i = 0; i < someArray.length; i++) {
// ^
An array returns undefined for a not existing item. undefined has no property to assign a new value.
var ObjectTest = function(something1, something2) {
this.Name = something1;
this.Job = something2;
this.color = '';
this.numbers = [];
};
var first = new ObjectTest('Paul', 'teacher');
var second = new ObjectTest('Jane', 'doctor');
var third = new ObjectTest('Mike', 'student');
var someArray = [];
someArray.push(first, second, third);
for (var i = 0; i < someArray.length; i++) {
someArray[i].color = 'red';
} // no semicolon here
console.log(someArray);

<= was rong
var ObjectTest = function(something1, something2){
this.Name = something1;
this.Job = something2;
this.color = '';
this.numbers = [];
}
var first = new ObjectTest('Paul', 'teacher');
var second = new ObjectTest('Jane', 'doctor');
var third = new ObjectTest('Mike', 'student');
var someArray = [];
someArray.push(first, second, third);
for(var i =0; i < someArray.length; i++){
someArray[i].color = 'red';
};
console.log(someArray);

Replace <= to < in your loop.
There's only 3 items on the array, meaning you have indexes 0, 1 and 2. The loop should stop when it arrives at at 3. But since you used <= and not <, i <= 3 when i is 3 is true thus executing the code. The error is caused by someArray[3] not existing.
A safer way to loop through arrays without dealing with indexes is to use array.forEach. It only loops as many times as there are items in the array.
someArray.forEach((object, index) => {
object.color = 'red'
})

An easier way to go over an array is to use the forEach.
Something like this:
someArray.forEach(data => data.color = 'red');

Related

Google Apps Script: Comparing Arrays for Unique Values

I'm working from the solution provided HERE to compare two arrays. The example provided returns values found in both arrays to Array1 (same) and values only found on one or the other two Array2 (diff).
ISSUE: When I apply it to my own script, valuesDATA returns nothing and valuesCheckSeeding returns ALL values from both arrays
DESIRED RESULT: I have two arrays that I'd either like to create a third out of, or only select values from the first array, valuesDATA which are NOT present in the second, valuesCheckSeeding. Using the solution above, I was trying to have all values not found in valuesCheckSeeding AND valuesDATA pushed to valuesDATA.
SAMPLE OF valuesDATA: "U09 F
Harford FC Hill/Healey - A
MD
CMSA Girls Saturday U09 A/B North
Premier - Top
TID0118"
What am I doing wrong? I tinkered with changing matchfound==false and matchfound=true in the loop, but that still didn't give me the desired result.
MOST RELEVANT SNIPPET
var matchfound = false;
for (var i = 0; i < valuesDATA.length; i++) {
matchfound=false;
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i] == valuesCheckSeeding[j]) {
valuesCheckSeeding.splice(j, 1);
matchfound=true;
continue;
}
}
if (matchfound==false) {
valuesCheckSeeding.push(valuesDATA[i]);
valuesDATA.splice(i, 1);
i=i-1;
}
}
WORKIG SCRIPT EDITED FROM COMMENTS/ANSWERS BELOW
//UPDATE SEEDING SHEET
function updateSeedingSheet() {
var today = Utilities.formatDate(new Date(),Session.getScriptTimeZone(), "MM/dd/yyyy hh:mm a");
//INPUT SHEET INFO
var inputCurrentRow = 4;
var inputCurrentColumn = 20;
var inputNumRows = 1000;
var inputNumColumns =1;
var ssInput = SpreadsheetApp.openById('1Wzg2BklQb6sOZzeC0OEvQ7s7gIQ07sXygEtC0CSGOh4');
var sheetDATA = ssInput.getSheetByName('DATAREF');
var rangeDATA = sheetDATA.getRange(inputCurrentRow, inputCurrentColumn, inputNumRows, inputNumColumns);
var valuesDATA = rangeDATA.getValues();
//SEEDING SHEET INFO
var seedingCurrentRow = 4;
var seedingCurrentColumn = 1;
var seedingNumRows = 1000;
var seedingNumColumns = 1;
var ssSeeding = SpreadsheetApp.openById('1DuCHeZ3zba-nHq-7vYTrylncPGqcA1J9jNyW9DaS3mU');
var sheetSeeding = ssSeeding.getSheetByName('Seeding');
var rangeCheckSeeding = sheetSeeding.getRange(4, 102, 1000, 1);
var columnToClear = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, seedingNumRows, seedingNumColumns);
var valuesCheckSeeding = rangeCheckSeeding.getValues();
//METHOD TO FILTER
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);
Logger.log(filteredArr.length);
var rangeSeeding = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, filteredArr.length, seedingNumColumns);
sheetSeeding.getRange('A1').setValue(today);
columnToClear.clearContent();
rangeSeeding.setValues(filteredArr);
/*
//ALTERNATIVE METHOD USING LOOPS
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log("VALUES DATA:" + valuesDATA);
Logger.log("VALUES CHECK SEEDING: " + valuesCheckSeeding);
//sheetSeeding.getRange('A1').setValue(today);
//rangeSeeding.clearContent();
//rangeSeeding.setValues(valuesDATA); //INCORRECT RANGE HEIGHT, WAS 71 BUT SHOULD BE 1000 - Is splice affecting this?
*/
}//END FUNCTION
V8(ES2016 update):
You can use newer and efficient set class
const array1 = [[1],[2],[3]],
array2 = [[1],[3],[4]],
set = new Set(array2.flat())
console.info(array1.filter(e => !set.has(e[0])))
//expected output [[2]]
You're checking a 2D array. You'd need to use [i][0] and [j][0]
You can try only splicing valuesDATA
Try
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log(valuesDATA);
Alternatively, try
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);

Array of objects contains same object over and over again

I create multiple objects and push them to the array objArr:
var objArr = [];
var obj = {};
var height = [9,8,7,3,6,5,2,4];
for (var i = 0; i < 8; i++) {
debugger;
var mountainH = height[i];
obj.h = mountainH;
obj.index = i;
objArr.push(obj);
}
for (var i = 0; i < objArr.length; i++) {
alert(objArr[i].h);
}
But as you can see, each object has the same values. Why?
Put the initialization of obj within your for-loop.
You were re-assigning new values to a global variable obj.
var objArr = [];
var height = [9,8,7,3,6,5,2,4];
for (var i = 0; i < 8; i++) {
debugger;
var obj = {};
var mountainH = height[i];
obj.h = mountainH;
obj.index = i;
objArr.push(obj);
}
for (var i = 0; i < objArr.length; i++) {
console.log(objArr[i].h);
}
Because the scope of obj in your code is global and it should rather be contained in the for loop.
If you will not declare it inside the loop then the value will get overwritten of the same obj on each iteration instead of a new memory allocation.
var objArr = [];
var height = [9, 8, 7, 3, 6, 5, 2, 4];
for (var i = 0; i < 8; i++) {
debugger;
var mountainH = height[i];
var obj = {};
obj.h = mountainH;
obj.index = i;
objArr.push(obj);
}
console.log(obj);
As noted, you need to initialize a new object in each iteration of the loop, otherwise all your array members simply share the same object reference.
Additionally, your code can be greatly reduced by building the array using .map(), and fully using the object literal initializer to declare the properties.
var height = [9,8,7,3,6,5,2,4];
var objArr = height.map((n, i) => ({h: n, index: i}));
console.log(objArr);
This is shorter and clearer. For every number in height, it creates a new object and adds it to a new array, which is returned from .map().
It can be even a little shorter with the newer features for object literals.
var height = [9,8,7,3,6,5,2,4];
var objArr = height.map((h, index) => ({h, index}));
console.log(objArr);

Array return undefined => values will not get pushed

function calculate(n1, n2, o) {
var num1 = (n1).toString();
var num2 = (n2).toString();
getNumber(num1);
getNumber(num2);
var valueArray = [x];
var number1;
var number2;
var counter2;
var newArray = [];
function getNumber(number){
var addition = 0;
var counter = num1.length - 1;
for(var i = 0; i < num1.length; i++){
if(number[i] != "0"){
addition += Math.pow(2, counter);
}
counter --;
}
newArray.push(addition);
}
}
calculate(1101, 1101);
I am trying to push the value of addition to newArray and am recieving an error saying "cannot read property push of undefined." Any thoughts?
You are calling getNumber(num1); before you initialise the array. Move the line var newArray = []; above your calls to getNumber
Basically 'newArray' is not initialized.
If you want to preserve 'newArray' between executions of the function:
if(!newArray)
newArray = new Array();
newArray.push(addition);

Array appending after each onclick and loop in javascript

This is the code fragment I have tried:
radio.onclick = function() {
var pp = e.target.result.split("\n");
var pq = pp.split('\n');
var pr = []; // array to append each values
for (var k = 0; k < pq.length; k++) {
var a = pq[0];
}
pr = a; // I need to create an array which should append again and again
}
In this code, after clicking a radio, a loop generates the value for the 'a' variable, whom it's added to array 'pr'. I want to add the generated value to 'pr' itself after the next on-click.
Is it possible?
Just define the array
pr
globally.
var pr = []; // array to append each values
radio.onclick = function() {
var pq = pp.split('\n');
for (var k = 0; k < pq.length; k++) {
var a = pq[0];
}
pr.push(a); // i need to create an array which should append again and again
}
But there you just get the last pq[0]of the loop
Hope that helps
You probably want to do this:
radio.onclick = function() {
var pq = pp.split('\n');
var pr = []; // array to append each values
for (var k = 0; k < pq.length; k++) {
pr.push(pq[k]);
}
}
If you need global access to pr just define it outside from radio.onclick.
Edit
even shorter:
radio.onclick = function() {
var pq = pp.split('\n');
}
or global
var pq = [];
radio.onclick = function() {
pq = pp.split('\n');
}
$(document).ready(function(){var array = new Array(); //Global declaration
radio.onclick = function(){
//do stuff here..
//get your value
array.push(your value);
}
});
//if you want to clear the array
array.splice();

initialize variable repeatedly using for loop in javascript

my question is can i possibly initialize variables repeatedly (with changing only numbers after them) this is my code
for(i = truStorage.getItem('elementCount'); i>0; i--) {
var obj = truStorage.getItem("element_" + i);
var [obj_+i] = element(erd.Entity , obj.posx, obj.posy, obj.text );}
};
basically i just want to initialize a variable like
something_i = "";
and the result will be like this
var element_1 = element(erd.Entity, 100, 200, "Employee");
var element_2 = element(erd.Entity, 100, 400, "Salesman");
var element_3 = element(erd.WeakEntity, 530, 200, "Wage");
var element_4 = element(erd.IdentifyingRelationship, 350, 190, "gets paid");
im not trying to use variables as a storage but rather to instantiate an element for a function.
This is a job for an array.
var something = [];
var somethings = 5;
for(var i = 0; i < somethings; i++) {
something[i] = "";
}
You should now be able to access the five values like this:
console.log(something[0])
console.log(something[1])
console.log(something[2])
console.log(something[3])
console.log(something[4])
Notice you use 0 to access the first element. That's just how it is because JavaScript arrays are zero-based.
This is best scenario to use array:
var counter=0,something = new Array();
for(i = truStorage.getItem('elementCount'); i>0; i--) {
something[counter] = truStorage.getItem("element_" + i).text;
counter++;
}
};
Try:
for(var i=1; i<=4; i++) {
this["something_" + i] = i;
}
console.log(something_1); //outputs 1;
console.log(something_2); //outputs 2;
console.log(something_3); //outputs 3;
console.log(something_4); //outputs 4;
Note: using an array will be faster!

Categories

Resources