I have some file contents I'd like to pass on to my server using a javascript function. In the file, there are many empty lines, or those which contain useless text. So far I read every line in as a string stored in an array.
How do I then loop through that content skipping multiple lines such as lines 24,25, 36, 42, 125 etc. Can I put these element id's into an array and tell my for loop to run on every element except these?
Thanks
you can't tell your for loop to iterate all, but skip certain elements. it will basically just count in any direction (simplified) until a certain critera has been met.
you can however put an if inside your loop to check for certain conditions, and chose to do nothing, if the condition is met. e.g.:
(pseudo code below, beware of typing errors)
for(var line=0; line < fileContents.length; line++) {
if(isUselessLine(line)) {
continue;
}
// process that line
}
the continue keyword basically tells the for loop to "jump over" the rest of the current iteration and continue with the next value.
The isUselessLine function is something you'll have to implement yourself, in a way, that it returns true, if the line with the given linenumber is useless for you.
You can try this its not much elegent but will suerly do the trick
<html>
<body>
<p>A loop which will skip the step where i = 3,4,6,9.</p>
<p id="demo"></p>
<script>
var text = "";
var num = [3,4,6,9];
var i;
for (i = 0; i < 10; i++) {
var a = num.indexOf(i);
if (a>=0) {
continue;
}
text += "The number is " + i + "<br>";
}
document.getElementById("demo").innerHTML = text;
</script>
</body>
You could use something like this
var i = 0, len = array1.length;
for (; i < len; i++) {
if (i == 24 || i == 25) {
array1.splice(i, 1);
}
}
Or you can have an another array variable which got all the items that need to be removed from array1
Another method:
var lines = fileContents.match(/[^\r\n]+/g).filter(function(str,index,arr){
return !(str=="") && uselessLines.indexOf(index+1)<0;
});
If you have many indices to skip, and this depends on the elements of the array, you could write a function that returns the number of elements to skip over for each index in that array (or returns 1, if no skipping required):
for ( let i = 0;
i < array.length;
i += calcNumberOfIndicesToSkip( array, i )){
// do stuff to the elements that aren't
// automatically skipped
}
function calcNumberOfIndicesToSkip( array, i ){
// logic to determine number of elements to skip
// (this may be irregular)
return numberOfElementsToSkip ;
}
In your case:
// skip the next index (i+1)?
for ( let i=0; i<array.length; i+=skipThisIndex(i+1) ){
// do stuff
}
function skipThisIndex(i){
const indicesToSkip = [ 24, 25, 36, 42, 125 ];
return 1 + indicesToSkip.includes(i);
}
// returns 1 if i is not within indicesToSkip
// (there will be no skipping)
// => (equivalent to i++; normal iteration)
// or returns 1 + true (ie: 2) if i is in indicesToSkip
// => (index will be skipped)
Related
I wonder if someone can clarify something for me. I have a bit of code to check an array for overlapping values depending on different values. Basically its the contents of a google sheet in rows and comumns for this is specifically GAS. What I have at the moment is
var e = [[2,4,3,4,2],[1,5,3,6,2],[2,4,3,4,1],[1,4,3,6,1],[2,4,3,6,5]];
var i; //id of entry to check
var j; //id of element to check
var k; //id of entry to compare
for (i in e){ //2D ARRAY ARRAY
for (k in e){ //ELEMENT TO COMPARE
if (e[i][2] === e[k][2] && e[i][3] === e[k][3] && e[i][0] && e[i][0] >= e[k][0] && e[i][1] <= e[k][1] && e[i][4] <= e[k][4] && i !=k){
e.splice(i,1);
continue;
}
}
}
return e;
I had to add the continue; as otherwise if the last array checked was also marked for splice the code failed. But I assumed break would also work in place of continue but for some reason it does not. I thought break would return to the outside loop but does it permanently break that bit of code?
Thanks people
EDIT: spoke too soon. code still fails even with continue. head scratching continues
continue jumps directly to the next iteration, so:
while(true) {
console.log("a");
continue;
console.log("b");
}
will only log a as it will jump back to the beginnig of the loop if it reaches continue.If you however move continue to the last line of the loop (just as in your code) it does nothing as it would jump to the begining to the loop one line later, so it just skips an empty line.
I thought break would return to the outside loop
Yup, thats what happens and that is actually a good thing as if you removed the element already, it won't make sense to check for other dupes as you don't want to remove it twice.
Now the real problem is that splice changes the indexes, so if you splice out the fourth element, the fith element becomes the fourth element, but the loop continues to the fith element without checking the fourth element again (which is now a different one). Therefore you have to go back by one element before you break:
for(let i = 0; i < e.length; i++) {
for(let k = 0; k < e.length; k++) {
if(i === k) continue; // < good usecase
if(/* equality checks */) {
e.splice(i, 1); // remove the element
i--; // go back by one as we changed the order
break; // exit the inner loop
}
}
}
IMO:
1) I would favor for(const [i, value] of arr.entries() over for..in
2) you will forget what arr[i][2] is very soon, giving proper names to the indexes makes it way more readable:
const [idA, someValueA] = e[i];
const [idB, someValueB] = e[k];
if(idA === idB && someValueA <= someValueB // ...
3) e is a bad name.
You can use a labelled break to break out of nested loops.
eg
var num = 0;
outermost:
for(var i = 0; i < 10; i++){
for(var j = 0; j < 10 ; j++){
if(i == 5 && j == 5){
break outermost;
}
num++;
}
}
I want the function NumberAddition to take a string and return an array of each number in it. For example argument "abc64,$ 22, 22xyz0" should return array [64, 22, 22, 0]. The 4th line in my for loop is the problem.
It's purpose is to move i up the string after a number is indexed so that it doesn't go over the same number again. If I delete this line the rest works fine with the problem of course being the same number being counted over and over until I naturally passes over it.
Why, when this line is included, does only the first number get counted (in my example the return would be [64]). I am less interested in other ways to solve it than why this line is not functioning how I had imagined it to. Thank you!
function NumberAddition(str) {
var array = [];
var nextInt;
for(var i = 0; i < str.length; i++){
nextInt = myParseInt(str.slice(i,10));
array.push(nextInt);
if (nextInt != null)
i = str.indexOf(nextInt,i) + nextInt.length -1;
else
break;
}
// code goes here
return array;
}
function myParseInt(str){
for(var i = 0; i < str.length; i++){
if (!isNaN(str[i]))
return parseInt(str.slice(i));
}
return NaN;
}
Numbers don't have a length; strings do. nextInt.length always returns undefined, which means you're setting i to NaN. Try nextInt.toString().length instead.
I am trying to get all combination of a number. For example, input "123" should return ["123", "231", "213", "312", "321", "132"].
Here is my function:
function swapDigits(input) {
for (var i = 0; i++; i < input.length - 1) {
var output = [];
var inter = input.slice(i, i + 1);
var left = (input.slice(0, i) + input.slice(i + 1, input)).split("");
for (var j = 0; j++; j <= left.length) {
var result = left.splice(j, 0, inter).join("");
output.push(result);
}
}
console.log(output);
return output;
}
However this function returns undefined, could anyone tell me what's going wrong?
The errors with the for loop and scope have already been mentioned. Besides that, the splice method will change the string that it operates on. This means that the inner loop will never terminate because left keeps on growing, so j never reaches left.length.
If you are new to a language, I would suggest starting with an implementation that is close to the algorithm that you want to implement. Then, once you are comfortable with it, use more advanced language constructs.
See this fiddle for an example. This is the algorithm code:
function getPermutations(input)
{
if(input.length <= 1)
{
return [input];
}
var character = input[0];
var returnArray = [];
var subPermutes = getPermutations(input.slice(1));
debugOutput('Returned array: ' + subPermutes);
for(var subPermuteIndex = 0; subPermuteIndex < subPermutes.length; subPermuteIndex++ )
{
var subPermute = subPermutes[subPermuteIndex];
for(var charIndex = 0; charIndex <= subPermute.length; charIndex++)
{
var pre = subPermute.slice( 0, charIndex );
var post = subPermute.slice( charIndex );
returnArray.push(pre+character+post);
debugOutput(pre + '_' + character + '_' + post );
}
}
return returnArray;
}
Basically, this will walk to the end of the string and work its way back constructing all permutations of sub-strings. It is easiest to see this from the debug output for 1234. Note that 'Returned array' refers to the array that was created by the permutations of the sub-string. Also note that the current character is placed in every position in that array. The current character is shown between _ such as the 1 in 432_1_.
Returned array: 4
_3_4
4_3_
Returned array: 34,43
_2_34
3_2_4
34_2_
_2_43
4_2_3
43_2_
Returned array: 234,324,342,243,423,432
_1_234
2_1_34
23_1_4
234_1_
_1_324
3_1_24
32_1_4
324_1_
_1_342
3_1_42
34_1_2
342_1_
_1_243
2_1_43
24_1_3
243_1_
_1_423
4_1_23
42_1_3
423_1_
_1_432
4_1_32
43_1_2
432_1_
This algorithm doesn't enforce uniqueness. So, if you have a string 22 then you will get two results - 22,22. Also, this algorithm uses recursion which I think is quite intuitive in this case, however there are pure iterative implementations if you look for them.
There are several errors in that code.
You have the order of the parts of the for statement incorrect. The order is initialization, test, increment. So for (/* init */ ; /* test */ ; /* increment */)
You're creating a new array for each iteration of your outer loop.
I'm making this a CW because I haven't checked for further errors than the above.
Hi I have an array that hold the following numbers, however when I loop though the eachNode function(which iterates 13 times) it repeats all the list elements 13 times. I tested everything but it still produces an error, I'm I executing the for loop correctly?
list[61,67,78]
var len = list.length;
fd.graph.eachNode(function (node) { // loops thru all node id's in graph (13)
for (var i = 0; i < len; ++i) {
if (i in list) {
var nody = list[i]; // I put the number in a variable
var nodess = fd.graph.getNode(nody); //this takes the number and matches it with a node id, it "odjectify" it
if (node.id != nodess.id) { // if the list nodes are not the same
node.setData('alpha', 0); //
node.eachAdjacency(function (adj) { // this make the unmatched nodes disappear
adj.setData('alpha', 0, 'end');
});
}
}
}
});
This line is unneeded:
if (i in list)
The in keyword returns true if its right operand contains the property specified by its left operand. When using this with arrays, it returns unexpected results. The behavior of this keyword is insignificant in this context, so you should simply take it out.
Moreover, you need to create the list array like this:
var list = [61, 67, 78];
...however, when I loop though eachNode (which iterates 13 times) it repeats all the list elements 13 times
It doesn't, it in fact iterates over eachNode 13 times. You also made a for loop which will traverse the list array by its length.
Now that you've given me more detail as to what you want, here is the updated code. I hope it works for you:
fd.graph.eachNode(function (node) {
var flag = false;
for (var i = 0; i < len; ++i)
{
var nody = list[i];
var nodess = fd.graph.getNode(nody);
if (node.id == nodess.id) {
flag = true; break;
}
}
if (flag)
{
node.setData('alpha', 0);
node.eachAdjacency(function (adj) {
adj.setData('alpha', 0, 'end');
});
}
});
This is the behavior by design:
You loop over the graph (13 times as you say), then inside each iteration you loop over your array (3 items).
If you only want to loop once over your array, just move it out of the outer loop
I have written the following:
var pages=["[www.google.co.uk] This is the WWW. ","[www.yahoo.co.uk] This is also the WWW. "];
function findScoresC(s){
var scores=[];
var words=[];
var wordScore;
var indexScore=[];
s=s.toLowerCase();
for(i=0;i<pages.length; i++){
var lowerCaseContents=(pages[i].substring(pages[i].indexOf("]")+1,pages[i].lastIndexOf(" "))).toLowerCase();
words=lowerCaseContents.split(" ");
for(i=0;i<words.length;i++){
if(words[i].match(s)){
wordScore=1;
indexScore[i]=indexScore[i]+1};
scores[i] =indexScore[i]}};
return scores;
}
alert(findScoresC("w"));
The function aims to return an array ("scores") where each index of the array is the number of times the string s is found in each index of the "pages" array, excluding what is inside the square brackets - however, only finding the string s once within each word. So ideally, the first index of scores would be 1, because I have called the function with the letter w, and i would only like it to find the first w of "WWW" in the first index of pages - if this makes sense.
I have confused myself pretty epically in getting this far, so I have no idea why the function is returning ",,,," rather than numerical values for each index of scores - any ideas?
Thanks
When your for loop exits, i is equal to words.length, which is one greater than the last index of indexScore. You are assigning nothing at all to scores[i] each time through.
It might be because you have a nested for loop with the same index variable.
var pages=["[www.google.co.uk] This is the WWW. ","[www.yahoo.co.uk] This is also the WWW. ";
function findScoresC(s){
var scores=[];
var words=[];
s=s.toLowerCase();
for(i=0;i<pages.length; i++)
{
scores[i]=0;
var lowerCaseContents=(pages[i].substring(pages[i].indexOf("]")+1,pages[i].lastIndexOf(" "))).toLowerCase();
words=lowerCaseContents.split(" ");
for(j=0;j<words.length;j++)
{
if(words[j].match(s))
{
scores[i] += 1;
}
}
}
return scores;
}
alert(findScoresC("w"));
There were a few things. I replaced "i" with "j" for the inner index. You don't require a semicolon after a closing paren. You should have a semicolon after instructions (a couple were missing).
Probably the main issue (after the "i" issue) was that scores[i] should have been set outside the inner loop. This would have been clearer if the cosing parens had been separated out onto separate lines, instead of like "scores[i] =indexScore[i]}};".
It turned out that the variable indexScore was not required. That allowed me to bring scores[i] inside the inner loop to accumulate word hits directly.
Finally, I would prefer to communicate the pages variable to the function as an argument than to assume that it is available in the global space. I tend to avoid globals if I can.
var pages = [...];
function findScoresC(pages, s)
{
...
}
alert(findScoresC(pages, "w"));
Here's you're function fixed. It returns [1,1] which appears to be what you were going for. My notes are in the code.
var pages=["[www.google.co.uk] This is the WWW. ","[www.yahoo.co.uk] This is also the WWW. "];
function findScoresC(s){
var scores = [],
words = [],
wordScore;
// indexScore = [] <- this doesn't seem necessary
s = s.toLowerCase();
// Make sure to use `var i` and not just `i`; otherwise, you are creating a global variable.
for ( var i=0; i<pages.length; i++ ) {
// Initialize me!
scores.push(0);
var lowerCaseContents = pages[i].substring(
pages[i].indexOf("]") + 1, pages[i].lastIndexOf(" ")
).toLowerCase();
words = lowerCaseContents.split(" ");
// You were using `i` for this loop as well. No can do.
for ( var j=0; j<words.length; j++) {
if ( words[j].match(s) ) {
// wordScore = 1; <- I don't know what you're using this for
scores[i]++;
}
}
};
return scores;
}
console.log(findScoresC("w"));
here's a small function that counts how many times substring "subStr" occurs in "str", not counting [...]
function substrCount(str, subStr) {
var str = str.replace(/\[.+?\]/g, "");
var del = str.toLowerCase().split(subStr.toLowerCase()).join("");
return (str.length - del.length) / subStr.length;
}
the rest is obvious ;)
// edit: this is how you apply this function to an array
var someArray = ["whatever", "something", "else" ];
var counter = [];
for(var i = 0; i < someArray; i++)
counter[i] = substrCount(someArray[i], "something");
// or, to count only one match, i.e. just to test if a substring is present
counter[i] = substrCount(someArray[i], "something") > 0;