views:

125

answers:

5

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

+2  A: 

It might be because you have a nested for loop with the same index variable.

Myles
OK I have tried renaming index variable of the nested for-loop to something else, and it now alerts "NaN,Nan". So at least it now recognises that there will be two indexes of the array scores...it just doesn't know what they are.
Deacon
indexScore[i] does not appear to ever get assigned to, yet it is attempted to be added with 1 to assign to itself and then indexScore. Perhaps you are expecting something to be there?
Myles
Well I would like indexScore[i] to be the "score" for pages[i], whereby the score is the sum of the wordScores (wordScore for each word is 1 if a match occurs, regardless of how many matches occur. 0 otherwise). Christ this is confusing me...
Deacon
+3  A: 

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.

Jonathan Feinberg
I don't quite understand what you're getting at...words.length is equal to the number of words in each index of pages. I intended for indexScore to be equal to the summation of all the wordScores within that index of pages.
Deacon
A: 

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;
stereofrog
If only it were...! I can understand your function (just about) but I can't understand how I can apply the mechanics of it to my function (and specifically, the fact that I only want to count 1 match for each word, regardless of how many matches actually occur).
Deacon
edited the post. oh, wait! seems you already found an answer... well, good luck then.
stereofrog
+1  A: 
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"));
Ewan Todd
Dang, ya beat me to it :)
JasonWyatt
Thank you so much! I can't believe how much I was overcomplicating things...thanks very much for your help. If I could, I would buy you several beers of your choice right now :-)
Deacon
A: 

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"));
Justin Johnson
Thanks very much for your reply - it would appear you were beaten to it by a few minutes, but as I can see the two replies are basically the same, thanks for your help :-)
Deacon