For-in loops with two variable javascript - javascript

Is this possible?
Two variable in for-in loops simulatenous?
for (var i in shear_x && var j in moment_x) {
var overturning_moment = (shear_x[i].results + moment_x[j].results)*moment_arm;
}

Your code implies, at least to me, that you really want a single loop counter applied over both objects, at the same time. I would suggest using a single for loop over the common length of the two objects:
var length = // length of shear_x
for (var i=0; i < length; ++i) {
var overturning_moment = (shear_x[i].results + moment_x[i].results) * moment_arm;
// rest of your loop code
}
If I interpreted your requirement incorrectly, then the only option which might come to mind is two nested loops, something like this:
for (var i in shear_x) {
for (var j in moment_x) {
// your code
}
}

Related

Array index out of bounds in Angular 2

I want to declare an Array with 4 dimensions, then loop some stuff with for() - and then the program breaks. Here is my code:
Typescript:
MoarInfo: any = [[[[]]]];
JavaScript:
constructor(){
for(var i = 0; i < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth].length; i++){
for(var a = 0; a < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i].length; a++){
for(var b = 0; b < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a].length; b++){
this.MoarInfo[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
this.MoarInfo[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
this.MoarInfo[i][a][b][2] = 'DetailsSpan';
}
}
}
}
The Problem definitively lies at the MoarInfo[][][][] array. I tested my code without it, and it works fine. I tried the following possibilities for the Typescript array declaration as well:
Moarinfo: any[]; MoarInfo = []; MoarInfo = [[[[]]]]; MoarInfo: any[][][][] = [[[[]]]];
And in JavaScript, I tried to declare a new Array, and then push some elements on the MoarInfo array, with different functions (split, unshift, push, concat) and nothing worked.
What am I doing wrong?
Check the size of this.MoarInfo[i][a][b]. You are trying to get the value by index 0,1,2. Looks like its size is less than 2 which is causing this error.
if(this.MoarInfo[i][a][b].size > 0){
this.MoarInfo[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
}
if(this.MoarInfo[i][a][b].size > 1){
this.MoarInfo[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
}
if(this.MoarInfo[i][a][b].size > 2){
this.MoarInfo[i][a][b][2] = 'DetailsSpan';
}
Okay, I figured it out for myself. You have to set the elements of the dimensions from the array at first blank, then you can fill them with content. First I declared an Array in TypeScript like this AnArray = [];. Then I switched to JavaScript ( to the constructer() function ) and filled it with blank elements. I archieved this with this.AnArray.push();. If you want to set elements for the first dimension use push([]);, if you want an element for the 4th dimension, use push([[[]]]);. And you can set your content space like this push([[['E1',0,0,'E2']]]);. Now you can use follwing syntax:
alert( this.AnArray[0][0][0][3] ); //returns 'E2'
The complete code from my project now works fine and looks like this:
for(var i = 0; i < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth].length; i++){
this.test.push([[[]]]);
for(var a = 0; a < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i].length; a++){
this.test[i].push([[]]);
for(var b = 0; b < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a].length; b++){
this.test[i][a].push(['',0,'']);
this.test[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
this.test[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
this.test[i][a][b][2] = 'DetailsSpan';
}
}
}
I wonder if there is a better way than using arrays, but if you want it too, you can do it like this.
cheers

How do I correctly split an array of strings of is it another issue?

I am trying to access a random element from an array of strings as per other examples here on SO. I am using Raphael.js and regions[j] below returns an array of Raphael objects - hence the .data(id). This seems to be ok, but theCountyNames, as outlined in the comment below returns all of the strings as one long string. I am guessing that this is why randCounty returns a single random letter, but when I try appending a comma in the loop (+",") and using split as per this question, I still get one random single letter. Perhaps I am implementing this incorrectly or maybe it is another issue? Thanks.
function pickRandCounty(){
var theCountyNames = new Array();
for (var j = 0; j < regions.length; j++) {
theCountyNames = regions[j].data('id');
document.write(theCountyNames);//THIS GIVES ME THE COMPLETE LIST OF ITEMS IN THE ARRAY BUT ALL AS ONE STRING
//document.write("<hr>");
}
//var randCounty = theCountyNames[Math.floor(Math.random() * theCountyNames.length)];
//document.write(randCounty);//THIS JUST RETURNS ONE RANDOM LETTER??
}
Using Array.prototype.push to append a new item to an Array.
function pickRandCounty(){
var theCountyNames = [],
j;
for (j = 0; j < regions.length; ++j) {
theCountyNames.push(regions[j].data('id'));
}
j = Math.floor(Math.random() * regions.length);
return theCountyNames[j];
}
However, this is not optimised as you can set the length of the Array in advance and you can even completely skip the loop,
function pickRandCounty(){
var j = Math.floor(Math.random() * regions.length);
return regions[j].data('id');
}
The error seems to be in this part of line.
theCountyNames = regions[j].data('id'); //wrong
theCountyNames.push(regions[j].data('id')); //right
Second mistake
document.write(theCountyNames); //it will keep on appending the string in the DOM
document.write("<br>" + theCountyNames);//right

for loop to print out multiple arrays with similar names

I've got multiple arrays, like so:
bugNames0 = ["wasp", "roach", "stinkbug", "mantis"];
bugNames1 = ["hornet", "beetle", "ant", "termite"];
bugNames2 = ["gnat", "fly", "grub", "chigger"];
bugNames3 = ["flea", "bed-bug","maggots", "cricket"];
Next up I have this for loop:
function bugLoop() {
for (var i=0; i < 4 ; i++){
console.log(bugNames0[i]);
}
}
That will successfully print the first array to console, or each individually if I manually update the number in the array's name.
But is there a way to do something more like this? This following code bit doesn't work, but I hope it explains what I am trying to do:
for (var i=0, j=0; i < 4; i++) {
console.log(bugNames(i)[j]);
}
}
Here i represents the bugName#, which I would like to get to update through 0 - 3 as the loop runs, printing out only the first option of each array represented by j.
Goal outcome printed to console would be:
"wasp", "hornet", "gnat", "flea"
Or something like that.
If possible I would like solutions only using vanilla JS as I'm working on a project (self assigned exercise) where I'm trying to complete it using vanilla. Kind of a force myself to get the know the language better exercise.
(Also, I've only been coding for 4 months, so sorry if this is a noob question. I couldn't find the answer online anywhere, just lots of loops on printing out arrays normally.)
If you can store your arrays within an array, that would be a better option.
For instance:
bugNames[0] = ["wasp", "roach", "stinkbug", "mantis"];
bugNames[1] = ["hornet", "beetle", "ant", "termite"];
bugNames[2] = ["gnat", "fly", "grub", "chigger"];
bugNames[3] = ["flea", "bed-bug","maggots", "cricket"];
Then you can loop through the bugNames array normally.
You could store all four arrays into one larger array (each bugNames array would simply be an element within this larger array). Let's call it bugCollection:
bugCollection = [["wasp", "roach", "stinkbug", "mantis"], ["hornet", "beetle", "ant", "termite"], ["gnat", "fly", "grub", "chigger"], ["flea", "bed-bug","maggots", "cricket"]]
Alternately, you could keep your variable storage of these arrays and say:
bugCollection = [bugNames0, bugNames1, bugNames2, bugNames3]
Then you could iterate through the larger array, logging out the index at each.
var oneFromEachArray = function(index) {
for (var i = 0; i < bugCollection.length; i++) {
console.log(bugCollection[i][index]);
}
}
oneFromEachArray(0) // Console logs 'wasp', 'hornet', 'gnat', 'flea'
You could try eval
for (var j=0; j < 4 ; j++){
for (var i=0; i < 4 ; i++){
eval("console.log(bugNames" + j + "[i]);");
}
}
You could use the function eval() like this:
for (var i=0, j=0; i < 4; i++) {
console.log(eval('bugNames' + i)[j]);
}
But did you already consider utilizing an array of arrays? Maybe that would be a cleaner way to achieve the same thing.
You can always access your variables using window object. Please use following code to access your variable dynamically.
for (var i=0, j=0; i < 4; i++) {
console.log(window["bugNames"+i][j]);
}

get string of values of certain property from JSON

I'm trying to get a string of ISBNs from a Google Books bookshelf via their API. Here's my attempt that isn't working. (I'm trying to use this snippet.)
$.getJSON("https://www.googleapis.com/books/v1/users/115939388709512616120/bookshelves/1004/volumes?key=MYAPIKEY", function (data) {
console.log(data);
var allIsbns = [];
for (i = 0; i < data.items.volumeInfo.industryIdentifiers[0].identifier.length; i++) {
allIsbns.push(data.items.volumeInfo.industryIdentifiers[0].identifier[i]);
}
alert(allIsbns);
});
fiddle
Looking at the object logged, data.items is an array (of length data.totalItems it seems). Furthermore, industryIdentifiers[0].identifier seems to be a string, and not an array. Therefore I think you wanted to loop through data.items instead.
Also it may be worth noting you probably should not be going by explicit index on industryIdentifiers unless the the spec calls out a predefined order. I would recommend finding the identifier with type === "ISBN_10":
for (var i = 0; i < data.items.length; i++) {
for (var j = 0; j < data.items[i].volumeInfo.industryIdentifiers.length; j++) {
if (data.items[i].volumeInfo.industryIdentifiers[j].type === "ISBN_10")
allIsbns.push(data.items[i].volumeInfo.industryIdentifiers[j].identifier);
}
}

Why is my nested for loop not working as I expected?

I have trouble dealing with my for loops now, I'm trying to compare two datum, basically it will compare 2 items, then it will write the matches and the mismatches on the webpage.
I managed to write the matches on the webpage, it was working good. But there's a bug in my mismatch compare.
It wrote all the data on the webpage X times, here's my JS code:
function testItems(i1, i2) {
var newArray = [];
var newArray2 = [];
var count = 0;
var count2 = 0;
for(var i = 0; i < i1.length; i++) {
for(var j = 0; j < i2.length; j++) {
if(i1[i] == i2[j]) {
newArray.push(i1[i]);
count++;
} if (i1[i] !== i2[j]) {
newArray2.push(i1[i]);
count2++;
}
}
}
count-=2;
count2-=2
writeHTML(count,count2, newArray, newArray2);
}
The result was horrible for the mismatches:
alt text http://www.picamatic.com/show/2009/03/01/07/44/2523028_672x48.jpg
I was expecting it to show the mistakes, not all the strings.
The issue you're seeing is because of the nested for loop. You are essentially doing a cross-compare: for every item in i1, you are comparing it to every item in i2 (remember that j starts again at 0 every time i advances... the two loops don't run in parallel).
Since I understand from the comments below that you want to be able to compare one array to the other, even if the items in each are in a different order, I've edited my original suggestion. Note that the snippet below does not normalize differences in case between the two arrays... don't know if that's a concern. Also note that it only compares i1 against i2... not both i1 to i2 and i2 to i1, which would make the task a little more challenging.
function testItems(i1, i2) {
var newArray = [];
var newArray2 = [];
for (var i = 0; i < i1.length; i++) {
var found = false;
for (var j = 0; j < i2.length; j++) {
if (i1[i] == i2[j]) found = true;
}
if (found) {
newArray.push(i1[i])
} else {
newArray2.push(i1[i])
}
}
}
As an alternative, you could consider using a hash table to index i1/i2, but since the example of strings in your comment include spaces and I don't know if you're using any javascript helper libraries, it's probably best to stick with the nested for loops. The snippet also makes no attempt to weed out duplicates.
Another optimization you might consider is that your newArray and newArray2 arrays contain their own length property, so you don't need to pass the count to your HTML writer. When the writer receives the arrays, it can ask each one for the .length property to know how large each one is.
Not directly related to the question but you should see this:
Google techtalks about javascript
Maybe it will enlighten you :)
Couple of things about your question. First you should use '!=' instead of '!==' to check inequality. Second I am not sure why you are doing decreasing counts by 2, suggests to me that there may be duplicates in the array?! In any case your logic was wrong which was corrected by Jarrett later, but that was not a totally correct/complete answer either. Read ahead.
Your task sounds like "Given two set of arrays i1 & i2 to find i1 {intersection} i2 and i1{dash} {UNION} i2{dash}) (Group theory notation). i.e. You want to list common elements in newArray and uncommon elements in newArray2.
You need to do this.
1) Remove duplicates in both the arrays. (For improving the program efficiency later on) (This is not a MUST to get the desired result - you can skip it)
i1 = removeDuplicate(i1);
i2 = removeDuplicate(i2);
(Implementation for removeDuplicate not given).
2) Pass through i1 and find i1{dash} and i1 {intersection} i2.
var newArray = [];
var newArray2 = [];
for (var i = 0; i < i1.length; i++)
{
var found = false;
for (var j = 0; j < i2.length; j++)
{
if (i1[i] == i2[j])
{
found = true;
newArray.push(i1[i]); //add to i1 {intersection} i2.
count++;
break; //once found don't check the remaining items
}
}
if (!found)
{
newArray2.push(i1[i]); //add i1{dash} to i1{dash} {UNION} i2{dash}
count2++;[
}
}
3) Pass through i2 and append i2{dash} to i1{dash}
for(var x=0; x<i2.length; x++)
{
var found = false;
//check in intersection array as it'd be faster than checking through i1
for(var y=0; y<newArray.length; y++) {
if( i2[x] == newArray[y])
{
found = true;
break;
}
}
if(!found)
{
newArray2.push(i2[x]); //append(Union) a2{dash} to a1{dash}
count2++;
}
}
writeHTML(count,count2, newArray, newArray2);
I have a feeling that this has to do with your second comparison using "!==" instead of "!="
"!==" is the inverse of "===", not "==". !== is a more strict comparison which does not do any type casting.
For instance (5 != '5') is false, where as (5 !== '5') is true. This means it's possible that you could be pushing to both arrays in the nested loop, since if(i1[i] == i2[j]) and if(i1[i] !== i2[j]) could both be true at the same time.
The fundamental problem here is that a pair of nested loops is NOT the right approach.
You need to walk a pointer through each dataset. ONE loop that advances both as needed.
Note that figuring out which to advance in case of a mismatch is a much bigger problem than simply walking them through. Finding the first mismatch isn't a problem, getting back on track after finding it is quite difficult.

Categories

Resources