I am using javascript, using regex to scrape images from html code.
I want the loop to run either until the script finds no more images or until it reaches 12.
I'm trying the following but not working:
var imgs = d.getElementsByTagName('img'), found = [];
for(var i=0,img; ((img = imgs[i]) || ( $i < 13)); i++)
Is this possible? Am I on the right lines?
Quite new to javascript but trying!
You should use && instead of ||. Also, $i should be i.
for(var i=0, img; (img = imgs[i]) && (i < 12); i++)
found.push(img);
Assuming that you want found to contain those first 12:
var imgs = d.getElementsByTagName('img');
var found = [].slice.call(imgs, 0, 12);
You have to use [].slice.call(imgs, ...) instead of imgs.slice() because imgs is only a pseudo-array, and not a real array.
An alternative to writing [].slice is Array.prototype.slice.
If you want to do something else inside the loop, just use the array created above to ensure that you only work on the first 12 images:
for (var i = 0, n = found.length; i < n; ++i) {
// do something with found[i];
}
I personally hate when people do assignment in the condition clause of a for loop, since it looks like someone mistook an assignment (=) for a comparison (=== or ==). Better to do the logic elsewhere.
var imgs = d.getElementsByTagName('img'),
found = [],
i,
imgsLength = imgs.length,
max = imgsLength > 13 ? 13 : imgsLength;
for (i = 0; i < max; i++) {
found.push(imgs[i]);
}
or
var imgs = d.getElementsByTagName('img'),
found = [],
i,
imgsLength = imgs.length;
for (i = 0; i < 13 && i < imgsLength; i++) {
found.push(imgs[i]);
}
For Loop with multiple statements
let products= [...]
let users= [...]
for(let i=0,userParam = null, productParam=null; i<products.length; i++, userParam=products[i], productParam=products[i]){
....
}
Related
Newer to coding and javascript and I am trying a codewars challenge. I setup an array to repeat a letter at certain indexes of my newArray based on a loop. For example if input was: cwAt expected output should be: C-Ww-Aaa-Tttt.
Been stuck on this for several hours (and have slept on it). I get error code:
newArray.join is not a function
when I try to run this and not sure what I can do to fix this problem. I feel its something simple and I just need to learn why this is happening.
function accum(s) {
let mumble = s.split('');
for (i = 0; i < mumble.length; i++) {
let newArray = [mumble[i].toUpperCase(), ''];
for (j = i; j > 0; j--) {
newArray = newArray.push(mumble[i]);
};
// Merge the new array into a string and set it at the mumble index required
mumble[i] = newArray.join('');
};
//Return new mumble with - as spaces between elements
return mumble.join('-');
}
console.log(accum('cwAt'));
Change newArray = newArray.push(mumble[i]); to newArray.push(mumble[i]);
push returns new length of the array.
You are storing a number in newArray. Try replace the 4 line with:
let newArray[i] = [mumble[i].toUpperCase(), ''];
and the 5 line :
for (j = 0; j < 0; j++) {
and the 6:
newArray[j] = newArray.push(mumble[i]);
I'm working on Google Script and I'm testing different ways to create two dimensions arrays.
I have created an array like this:
var codes = new Array(6);
for (var i = 0; i < 6; i++) {
codes[i] = new Array(4);
}
codes[0][0]="x";
codes[0][1]="x";
codes[0][2]="x";
codes[0][3]="x";
codes[1][0]="x";
codes[1][1]="x";
codes[1][2]="x";
codes[1][3]="x";
codes[2][0]="x";
codes[2][1]="x";
codes[2][2]="x";
codes[2][3]="x";
codes[3][0]="x";
codes[3][1]="x";
codes[3][2]="x";
codes[3][3]="x";
codes[4][0]="x";
codes[4][1]="x";
codes[4][2]="x";
codes[4][3]="x";
codes[5][0]="x";
codes[5][1]="x";
codes[5][2]="x";
codes[5][3]="x";
And it is working fine.
I read following links here, here and here.
But when I do it like this:
var codes = new Array(6);
for (var i = 0; i < 6; i++) {
codes[i] = new Array(4);
}
codes[0]=["x","x","x","x"];
codes[1]=["x","x","x","x"];
codes[2]=["x","x","x","x"];
codes[3]=["x","x","x","x"];
codes[4]=["x","x","x","x"];
codes[5]=["x","x","x","x"];
It didn't work, so I tried like this:
var codes = new Array([["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"]]);
it didn't work either.
When the code don't work, I get no error, just no display of the values.
What am I doing wrong? It looks to be the same code and the two not working ways are recommended in many documentations.
W3schools says that there is no need to use new Array().
For simplicity, readability and execution speed, use literal method ex:
var animals = ["cat", "rabbit"];
Reason why your code was not working is that you're equaling codes inside the loop and after end of loop scope 'codes' is getting only the last set array. Instead you should push those arrays to codes.
var codes = [];
for (var i = 0; i < 6; i++) {
codes.push([i]);
}
console.log(codes)
codes[0]=["x","x","x","x"];
codes[1]=["x","x","x","x"];
codes[2]=["x","x","x","x"];
codes[3]=["x","x","x","x"];
codes[4]=["x","x","x","x"];
codes[5]=["x","x","x","x"];
Better yet, two for loops to create the double array:
var codes = [], // Initiate as array, in Javascript this is actually fastre than using new (I don't know any cases you should use new)
rows = 6,
columns = 6;
for (var i = 0; i < rows; i++){
codes.push([]); // Initiate
for (var j = 0; j < columns; j++){
codes[i][j] = 'x';
}
}
Other idea, pre-initiate an array with the correct columns then copy:
var arrTemp = [],
codes = [],
rows = 6,
columns = 6;
for (var j = 0; j < columns; j++)
arrTemp[i] = 'x';
for (var i = 0; i < rows; i++)
codes.push( arrTemp.slice(0) ); // If you just push the array without slice it will make a reference to it, not copy
Other way to pre-initiate the array with 'x's:
arrTemp = Array.apply(null, Array(columns)).map(function () {return 'x'});
I have the following javascript
information0 = xmlDoc.getElementsByTagName("info")[0].textContent;
information1 = xmlDoc.getElementsByTagName("info")[1].textContent;
information2 = xmlDoc.getElementsByTagName("info")[2].textContent;
information3 = xmlDoc.getElementsByTagName("info")[3].textContent;
information4 = xmlDoc.getElementsByTagName("info")[4].textContent;
information5 = xmlDoc.getElementsByTagName("info")[5].textContent;
information6 = xmlDoc.getElementsByTagName("info")[6].textContent;
I want to create a new var for each index number. There are 600 in total. How can I do this using a for loop?
Thanks in advance
The best thing here is to use an array, not a bunch of individual variables.
var information = [];
var index;
var info = xmlDoc.getElementsByTagName("info");
for (index = 0; index < info.length; ++index) {
information[index] = info[index].textContent;
}
Um... use an array? Also, don't call getElementsByTagName repeatedly, it's expensive!
var tags = xmlDoc.getElementsByTagName('info'), l = tags.length, i, information = [];
for( i=0; i<l; i++) information[i] = tags[i].textContent;
If you're in a reasonably up-to-date browser:
var information = [].map.call(xmlDoc.getElementsByTagName('info'),function(a) {return a.textContent;});
Like this:
var information = [],
i,
elements = xmlDoc.getElementsByTagName("info"),
n = elements.length;
for (i = 0; i < n; ++i) {
information[i] = elements[i].textContent;
}
You need to use an array.
var infoTags = xmlDoc.getElementsByTagName("info"),
i = 0,
len = infoTags.length,
values = []; //array literal syntax, you could also use new Array()
for (; i < len; i++) {
values.push(infoTags[i].textContent); //push the textContent into the array
}
Things that you should note:
I cached the result of getElementsByTagName instead of performing the query multiple times.
I cached the length property of infoTags. That avoids multiple property lookups to access infoTags.length on every iterations. Property lookups are expensive in JavaScript.
To know how you can work with arrays, have a look at the Array object.
-
Hello there am trying to save news tweets into three different array which are dynamically created.
am finding trouble when i want to get the text from each one of those array and make another request to twitter.
news_tweets("reuters","1652541",3);
function news_tweets(query, user_id,count) {
news_array = [];
$.getJSON("https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=false&user_id=" + user_id + "&count="+count+
"&callback=?",
function (data) {
for (var i = 0; i < count; i++) {
var user = data[i].user.name;
var date = data[i].created_at;
var profile_img = data[i].user.profile_image_url;
var text = data[i].text;
var url = (data[i].entities.urls.length > 0 ? data[i].entities.urls[0].url : '');
news_array[i] = [{user:user,date:date,profile_img:profile_img,text:text,url:url}];
}
for (var i = 0; i < news_array.length; i++) {
for (var x=0; x<i.length; x++){
console.log(news_array[i][x].user);
}
}
});
}
It doesn't show anything on the console.log.
thanks for the help!!!!!
First, make sure that your count is smaller than the data array's length, otherwise this could lead to some undefined values:
for (var i = 0; i < count && i < data.length; i++) …
Then, why are you creating all those one-element-arrays in the news_array? Just use only objects.
This would solve your actual issue: You are looping wrong over those inner arrays. The correct code would be
for (var i = 0; i < news_array.length; i++) {
for (var x = 0; x < news_array[i].length; x++){
console.log(news_array[i][x].user);
}
}
Also, you should indent your code properly. You have some odd braces around, which don't make the code readable.
The problem is the x<i.length in the for loop near the end. i is a number, so it doesn't have a length. You probably meant x < news_array[i].length.
You may try the following:
Use the push method to append elements / data in your array new_array
Use only 1 loop for to display the user value on console
So your code will be something like this:
news_tweets("reuters","1652541",3);
function news_tweets(query, user_id,count) {
news_array = [];
$.getJSON("https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=false&user_id=" + user_id + "&count="+count+
"&callback=?",
function (data) {
for (var i = 0; i < count; i++) {
var user = data[i].user.name;
var date = data[i].created_at;
var profile_img = data[i].user.profile_image_url;
var text = data[i].text;
var url = (data[i].entities.urls.length > 0 ? data[i].entities.urls[0].url : '');
// Pushing your elements in your array, 1 by 1
news_array.push({user:user,date:date,profile_img:profile_img,text:text,url:url});
}
// Here you only need 1 loop!
for (var i = 0; i < news_array.length; i++) {
console.log(news_array[i][x].user);
}
});
}
First thing is i would loop the first one till data.length rather than count because its an api and it "might" or "might not" return all the data. So it will be fool proof to loop till data.length
And your problem is with i.length
for (var i = 0; i < news_array.length; i++) {
console.log(news_array[i].user);
}
this should work. not sure why you had to loop through a loop.
I have stumbled into several methods of looping in JavaScript, what I like the most is:
for(var i = 0; i < a.length; i++){
var element = a[i];
}
But as tested here (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/), it should probably be written so that the length is only calculated once.
In jQuery there is a .each that you can stick a function. I like this a little better, because I don't have to type the array twice, like in the above solution.
If JavaScript supported macros it would be a piece of cake to roll your own, but sadly it does not.
So what do you guys use?
I've started using iterators where relevant. Performance is reasonable, however more importantly it allows you to encapsulate the looping logic:
function createIterator(x) {
var i = 0;
return function(){
return x[i++];
};
}
Then to use:
var iterator=createIterator(['a','b','c','d','e','f','g']);
iterator();
returns "a";
iterator();
returns "b";
and so on.
To iterate the whole list and display each item:
var current;
while(current=iterator())
{
console.log(current);
}
Be aware that the above is only acceptable for iterating a list that contains "non-falsy" values. If this array contained any of:
0
false
""
null
NaN
the previous loop would stop at that item, not always what you want/expect.
To avoid this use:
var current;
while((current=iterator())!==undefined)
{
console.log(current);
}
Small improvement to the original, to only calculate the array size once:
for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }
Also, I see a lot of for..in loops. Though keep in mind that it's not technically kosher, and will cause problems with Prototype specifically:
for (i in a) { var element = a[i]; }
Just store the length in a variable first.
var len = a.length;
for (var i = 0; i < len; i++) {
var element = a[i];
}
I know I'm late to the party, but I use reverse loops for loops that don't depend on the order.
Very similar to #Mr. Muskrat's - but simplifying the test:
var i = a.length, element = null;
while (i--) {
element = a[i];
}
You could just always use a while loop, and compute the array limit before hand.
Var max = a.length-1;
var i = 0;
while(i <= max)
{
var element = a[i];
i++;
}
If you have many elements in the array and speed is an issue then you want to use a while loop that iterates from highest to lowest.
var i = a.length;
while( --i >= 0 ) {
var element = a[i];
// do stuff with element
}
I don't use it myself, but one of my colleagues uses this style:
var myArray = [1,2,3,4];
for (var i = 0, item; item = myArray[i]; ++i) {
alert(item);
}
like Ash's answer, this will hit issues if you've got "falsey" values in your array. To avoid that problem change it to (item = myArray[i]) != undefined
I don't see what the problem with using a standard for(;;) loop is.
A little test
var x;
var a = [];
// filling array
var t0 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
a[i] = Math.floor( Math.random()*100000 );
}
// normal loop
var t1 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
x = a[i];
}
// using length
var t2 = new Date().getTime();
for( var i = 0; i < a.length; i++ ) {
x = a[i];
}
// storing length (pollution - we now have a global l as well as an i )
var t3 = new Date().getTime();
for( var i = 0, l = a.length; i < l; i++ ) {
x = a[i];
}
// for in
var t4 = new Date().getTime();
for( var i in a ) {
x = a[i];
}
// checked for in
var t5 = new Date().getTime();
for( var i in a ) {
if (a.hasOwnProperty(i)) {
x = a[i];
}
}
var t6 = new Date().getTime();
var msg = 'filling array: '+(t1-t0)+'ms\n'+
'normal loop: '+(t2-t1)+'ms\n'+
'using length: '+(t3-t2)+'ms\n'+
'storing length: '+(t4-t3)+'ms\n'+
'for in: '+(t5-t4)+'ms\n'+
'checked for in: '+(t6-t5)+'ms';
console.log( msg );
results in:
filling array: 227ms
normal loop: 21ms
using length: 26ms
storing length: 24ms
for in: 154ms
checked for in: 176ms
So:- for in's take the longest, using the length property (which is a property and doesn't need to be calculated) is nearly as fast as storing it first - which is only a whisker slower than using an integer.
AND a for() is the usual way to loop over an array, which everyone expects and understands.
All of them add a variable to the scope they run in - i - which is a common name for this use and so shouldn't be used for other things. Storing the length first adds another var - l - to the scope, which is unnecesary
So, first you identify the perfect javascript loop, I believe it should look like this:
ary.each(function() {$arguments[0]).remove();})
This may require the prototype.js library.
Next, you get disgustet with the arguments[0] part and have the code be produced automatically from your server framework. This works only if the ladder is Seaside.
Now, you have the above generated by:
ary do: [:each | each element remove].
This comes complete with syntax completion and translates exactly to the above javascript. And it will make people's head spin that haven't used seasides prototype integration before, as they read your code. It sure makes you feel cool, too. Not to mention the gain in geekiness you can get here. The girls love it!