Searching AFINN-165 json by score - javascript

I'm making a emotion-adjusted Youtube search engine which maps a score (read from webcam images by Microsoft Azure Emotion API) to a few words selected in the AFINN-165 list, and then peforms a Youtube search.
The code is written in Node & Express (returns the answer by GET request).
I'm trying to search the JSON by value of a word. Example; When I give the function (5) it would return all words that have a score of five.
The JSON is structured like this:
var data = {
word: score,
word: score,
word: score,
};
Which I wrap in an array below
function getWordsByScore() {
var afinnKeys = Object.keys(afinn);
var afinnArray = [afinn]
console.log(afinnKeys.length);
for (var i = 0; i < afinnKeys.length; i++) {
var word = String(afinnKeys[i]);
return(afinnArray[0].word);
}
}
Somehow I just can't get it to work. I try to get the actual 'word' by creating an array of keys in AfinnKeys. But feeding this word by a forloop to the afinnArray[0] just gives undefined as a return.
I hope someone could help me out. Have been stuck on this for some time now.

Would something like this help you?
var score = 3;
var data = {
'firstword': 1,
'secondword': 2,
'thirdword': 3,
'forthword': 3
};
var result = Object.keys(data).filter(function (key) {
return data[key] === score
});
console.log(result);

The reason you're getting undefined is because your for loop runs once and then returns immediately.
The value it tries to return is afinnArray[0].word which looks for the property word on the afinnArray[0] object when you may have meant to do afinnArray[0][word] which uses the string variable word as the property name.
You also never pass the score to the function so as it is it won't be based on the score.
All you really need to do is to compare the score passed in to the function to the score in the afinn object by using the word from the word variable obtained your for loop as the key (and it's already a string so there's no need to cast it to one). Then, if the scores match, push the word to a new array. Once the for loop completes, return the new array.
var afinn = {
a: 1,
b: 1,
c: 0,
d: 0,
e: 2,
f: 2
};
function getWordsByScore(score) {
var afinnKeys = Object.keys(afinn);
var afinnArray = []
for (var i = 0; i < afinnKeys.length; i++) {
var word = afinnKeys[i];
if(afinn[word] == score){
afinnArray.push(word)
}
}
return afinnArray
}
console.log(getWordsByScore(1))
Or as another commenter suggested, use Array#filter

Related

Get text between 2 or more substrings

This is my first question, so excuse me if I mess something up. I'm new.
Anywho, recently I've been designing a function which takes a string and 2 substrings, and then returns an array of the positions of both substrings so I can later substring the actual string using the positions of the substrings I'm searching for. I hope that makes sense.
function m(s,s1,s2,prevTable){
var a = prevTable || []
if (s.indexOf(s1) > -1 && s.indexOf(s2, s.indexOf(s1)) > -1){
a.push([s.indexOf(s1),s.indexOf(s2, s.indexOf(s1))+s2.length])
s=s.substring(s.indexOf(s2, s.indexOf(s1)+s2.length))
console.log(s)
m(s,s1,s2,a);
}
return a;
}
So to summarize it makes an array (a), finds the position of s1 and s2 (plus it's own length so it includes s2) in the source string (s), adds them to the array as it's own array.
E.g a would be: a=[[2,5]], deletes up to where s2 was found (+s2.length to include s2), and then repeats it with the new string unless it can't find both s1 and s2, in which case it returns a.
However, it does not work as I intended it to.
Upon running this:
var s = "Hey. This is pointless. Middle is always neutral. This is not
pointless."
var a=m(s,"This","pointless.")
for (i=0;i<a.length;i++){
console.log(s.substring(a[i][0],a[i][1]))
}
The result I get is:
This is pointless.
dle is always neutral.
When I am expecting:
This is pointless.
This is not pointless.
Also, is there a name for this technique?
What you are trying to do could be accomplished more easily using regular expressions (MSDN Docs).
Here is a simple example, note: I threw this together quickly, it may not handle all input perfectly.
function splitBetweenTwoStrings(str, s1, s2){
var reg = new RegExp("("+s1+".*?"+s2+")", "g");
var result = [];
var r = null;
//get all instances and push into result array
while((r=reg.exec(str))){
result.push(r[1]);
}
return result;
}
console.log(splitBetweenTwoStrings("Hey. This is pointless. Middle is always neutral. This is not pointless.","This","pointless."))
You could do it by creating another method to check indices (I received help from (here)[https://stackoverflow.com/a/20968478/7535444]) and then loop over the occurrences.
var s = "Hey. This is pointless. Middle is always neutral. This is not pointless.";
var results = m(s, "This", "pointless.");
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
}
function m(s, s1, s2) {
var s1Occurences = occurences(s, s1);
var s2Occurences = occurences(s, s2);
var loopCount = Math.min(s1Occurences.length, s2Occurences.length);
var results = [];
for (var i = 0; i < loopCount; i++) {
results.push(s.substring(s1Occurences[i], s2Occurences[i] + s2.length));
}
return results;
}
function occurences(main, sub) {
var indices = [];
for(var pos = main.indexOf(sub); pos !== -1; pos = s.indexOf(sub, pos + 1)) {
indices.push(pos);
}
return indices;
}
The problem with your code is, that in your example the second array element of "a" ([[5,23],[27,49]]) is relative to the temporary "s"-string created for the second call of m(). You would have to shift the values by the length of the cut-off-part of the "s"-string: [[5,23],[27+23,49+23]].
But I would recommend to use something like Will P.'s method.

javascript enum auto-increment?

In objc I can use the enum like this:
typedef enum {
STATE_A = 1,
STATE_B,
STATE_C,
......
STATE_KK = 100,
STATE_FF,
......
STATE_XXX = 99999
} State;
the value of each variable is auto increased (compared to the former one).
but in javascript, I need to:
var State = {
STATE_A: 1,
STATE_B: 2,
STATE_C: 3,
......
STATE_KK: 100,
STATE_FF: 101,
......
STATE_XXX = 99999
}
you see I need to specify all the values for each varible and this is really sick when you
got lots of varible there and it gets even sicker when you try to insert a variable in between so that
you have to ask yourself (what the value it should be ???)
I'm quite new to js and really wants to know if there is a way to use enum in js the way like in other languages
such as objc I mentioned.
Thanks :)
its kind of ugly, but you could do:
var i=1;
var State = {
STATE_A: i++,
STATE_B: i++,
STATE_C: i++
}
How about giving them all an initial value of 0 then setting their values in a loop
var State = {
STATE_A: 0,
STATE_B: 0,
STATE_C: 0,
......
STATE_KK: 0,
STATE_FF: 0,
......
STATE_XXX = 0
}
var count=0;
for(var key in State){
State[key]=count++;
}
You can create your little enum maker that both auto-numbers them and lets you set any values you want (kind of like the features you have in objectiveC:
function makeEnum(list) {
var obj = {}, sequence = 0, current;
for (var i = 0; i < list.length; i++) {
current = i;
if (typeof list[i+1] === "number") {
sequence = list[i+1];
i++;
}
obj[list[current]] = sequence++;
}
return(obj);
}
var State = makeEnum(["STATE_A","STATE_B","STATE_C", "STATE_KK", 100, "STATE_LL"]);
Anywhere you put a number in the passed in array, it sets the value of the previous enum value and the sequence then continues from that value.
If I understand correctly your goal is to identify states with numbers in order to make them comparable in enums.
First here is a working fiddle of what I think you meant.
For general enums, here is a nice trick I use:
function createEnum(values){
var res={};
for(var i=0;i<values.length;i++){
res[values[i]]=i;//add the property
}
//Object.freeze(res);//optional to make immutable
return res;
};
This allows the following syntax
var State = createEnum(["STATE_A","STATE_B","STATE_C"]);
This means you don't have to explicitly define an integer value for all the states, one is given. After that you can use it normally
State.STATE_A===State.STATE_B;//returns 1
If you'd like to fill based on a pattern, you can extend this the following way (assuming your syntax):
function createEnumPattern(prefix,range){
var res={},str="a";
for(var i=0;i<range;i++){
var pattern = prefix+"_"+inc_str(str);
res[pattern]=i;//add the property
}
//Object.freeze(res);//optional to make immutable
return res;
}
Where inc_str is from this answer.
So for example
var State = createEnumPattern("State",100);
Will return a State enum with properties like State_aa and so on, if you'd like you can use toUpperCase on it to force the upper case convention you use.

JavaScript; n-dimensional array creation

In the process of building a JavaScript interpreter for a simple language, I've faced the following problem;
After parsing, we get an array of indices that specifies the element in an n-dimensional array to be modified. For instance, after parsing this:
a[1, 1, 1]
We get an array [1, 1, 1]. The language I'm working on doesn't have variable definitions, so variables get initialized on their first use. My goal is to be able to create this n-dimensional array so that I can place it in the variable table (in the example above, we'd need to create a 3-dimensional array).
The short question:Is there a way to create an n-dimensional array in JavaScript without using eval()?
Tested in Chrome:
function createNDimArray(dimensions) {
if (dimensions.length > 0) {
var dim = dimensions[0];
var rest = dimensions.slice(1);
var newArray = new Array();
for (var i = 0; i < dim; i++) {
newArray[i] = createNDimArray(rest);
}
return newArray;
} else {
return undefined;
}
}
Then createNDimArray([3, 2, 5]) returns a 3x2x5 array.
You can use a similar recursive procedure to access an element whose index is in an array:
function getElement(array, indices) {
if (indices.length == 0) {
return array;
} else {
return getElement(array[indices[0]], indices.slice(1));
}
}
Setting an element is similar, and left as an exercise for the reader.
There's nothing built in, but it's pretty easy to create a function that would do the job:
var genArray = function () {
var arr, len, i;
if(arguments.length > 0) {
len = [].slice.call(arguments, 0, 1)[0];
arr = new Array(len);
for(i = 0; i < len; i++) {
arr[i] = genArray.apply(null, [].slice.call(arguments, 1));
}
} else {
return null; //or whatever you want to initialize values to.
}
return arr;
};
var a = genArray(3, 2); //is [[null, null],[null, null],[null, null]]
var b = genArray(3, 1, 1); //is [[[null]],[[null]],[[null]]]
a[0][1]; //is null
b[1][0][0]; //is null
b[1][0][0] = 3;
b[1][0][0]; //is 3;
b; //is [[[null]],[[3]],[[null]]]
Maybe that will help?
PS --
I know this might seem like more effort than is necessary. But unfortunately, JavaScript arrays are not really "arrays" (if by "array" you mean a contiguous, indexed, immutable memory block). They're more like "maps" in most languages. So there's a certain amount of effort involved in creating them. Most languages have no problem creating multi-dimensional arrays because they're just doing some simple multiplication followed by an malloc(). But with JavaScript, you really have to go recursively generate your arrays if you want to have them pre-constructed. It's a pain, but it does demonstrate the effort required by the interpreter.
Go figure.
For creating an n-dimensional array:
function createNDimArray(dimensions) {
var ret = undefined;
if(dimensions.length==1){
ret = new Array(dimensions[0]);
for (var i = 0; i < dimensions[0]; i++)
ret[i]=null; //or another value
return ret;
}
else{
//recursion
var rest = dimensions.slice(1);
ret = new Array(dimensions[0]);
for (var i = 0; i < dimensions[0]; i++)
ret[i]=createNDimArray(rest);
return ret;
}
}
EDIT: Due to the fact that any recursive solution will have a limit to the size of the array you can create... I made another solution in my
PJs # GitHub library. This one runs at pseudo-instant speed and can create and manage a multidimensional array of any size, any structure, with any dimensions at any branch. It also can simulate prefilling and/or use a node object of custom design. Check it out here: https://github.com/PimpTrizkit/PJs/wiki/14.-Complex-Multidimensional-Object--(pCMO.js)
Using a modified version of jfabrizio's solution:
function createNDimArray(dimensions) {
var t, i = 0, s = dimensions[0], arr = new Array(s);
if ( dimensions.length < 3 ) for ( t = dimensions[1] ; i < s ; ) arr[i++] = new Array(t);
else for ( t = dimensions.slice(1) ; i < s ; ) arr[i++] = createNDimArray(t);
return arr;
}
Usages:
var arr = createNDimArray([3, 2, 3]);
// arr = [[[,,],[,,]],[[,,],[,,]],[[,,],[,,]]]
console.log(arr[2][1]); // in FF: Array [ <3 empty slots> ]
console.log("Falsy = " + (arr[2][1][0]?true:false) ); // Falsy = false
I found this to be quite a bit faster. I might stretch to say that it could be the fastest way possible to generate a N Dimensional array in Javascript. This refactoring above had some good speed increases. But, the best speed increase came from not prefilling, of course. This version doesn't prefill the array. It only returns a fully created N dimensional array of Ns lengths where the last level is just an empty array. I would hope that arr[x][y][z]?arr[x][y][z]:null is sufficient if you really need the null value. It is for my uses. :)
If you need prefilling, use his original version.
And, if you don't really care about what I did; then stop reading.
Want more geek talk? A little something about recursion for those learning out there. Alright here are the tactics. When doing deep recursion, keep in mind the final level. Its where most of the work is done. In this case its the Nth dimension, literally. This is your "payload", the rest is logistics. In jfab's function, when dimensions.length gets to 1, its last dimension, its in the Nth dimension and performs the payload. Which is to create the array of nulls, or in my case, an empty array. Since the recursion gets so deep each dimension is a factor of the last one. By the time you get to the Nth dimension you will have a lot of function calls and logistics gets cumbersome to the computer. And at the Nth dimension you will call your base recursion function (createNDimArray in our case) more times for the payload than you will for logistics. Now, as in jfab's original solution, putting the execution of the payload as the very first thing you do in recursion (if possible) is usually a good thing, especially if its simple. Here, by making the payload a building of the final 2D array (instead of just a 1D array by simply returning a new Array() only). Then the excessive amount of function calls now don't have to happen at this level. Now, of course, if you want to prefill the array, then this shortcut doesn't always help. But more to the point, prefilling the array would be the appropriate payload. By not visiting every item on the Nth dimension we have effectively removed it. That way there is one less level of function calls and basically the Nth dimension's payload is actually done on the N-1 th Dimension. And we are never calling the recursive function again just to deliver the new Array(). Unfortunately, the call to new Array(x) (in general) doesn't see it that way. Its execution time does increase with a larger x. Which is effectively still visiting every item in the Nth Dimension, but now we do it only once and with native code and wrapped in a tight and light loop. Now we require that createNDimArray can only be called with N > 1, ie never used to create 1D arrays. Theoretically you could require a larger N, and unroll even more dimensions at the end. Basically, the line with if ( dimensions.length < 3 ) will read something like < 4 or < 5 and you would have to wrap that many more for loops around the one thats there, and they would each all need their own set of vars --- so I'm not sure how efficient it all might be, as you are trading excessive function call and stack space/manipulation with a similar idea but in embedded for loops --- But I suppose it could speed up some environments if you know that N is always above a certain level or if its only for the final dimensions. Like here, I did it for the last two dimensions. But if you unroll too much, then your payload itself is a bear. Only testing will tell if thats worth it. It does seem that stack space is limited, and I think I remember having been able to make larger arrays with more unrolling. There is a limit to how big you can make an array. And recursion solutions that call themselves for each item at the Nth level had the lowest limit if I do.. recall.. correctly.... much lower.
The next part in revising his solution is just the logistics, its was just a simple refactor to get rid of excessive blocks and code. Join all the var work together and thats it. Since you need a arr to return, once the looping is over, might as well do all your var work on one line first and luckily, three of the four vars have the same initialization. Remember, Javascript can optimize code when joining with , if possible. This also makes for smaller code as well.
PT
One more version of createNDimArray using map, apply and bind functions:
function createNDimArray(dims) {
return dims.length === 1
? new Array(dims[0])
: Array.apply(null, Array(dims[0])).map(createNDimensionalArray.bind(null, dims.slice(1)));
}
createNDimArray([3, 2, 5]); // returns 3x2x5 array
Creating an ND Array requires cloning nested ND arrays. Accordingly you will need a proper Array.prototype.clone() method and the rest is easy. To my knowledge the following is the simplest and most efficient way in JS.
Array.prototype.clone = function(){
return this.reduce((p,c,i) => (p[i] = Array.isArray(c) ? c.clone() : c, p),[])
}
function arrayND(...n){
return n.reduceRight((p,c) => c = (new Array(c)).fill().map(e => Array.isArray(p) ? p.clone() : p ));
}
var NDarr = arrayND(4,4,4,4,"."); // size of each dimension and the init value at the end
console.log(JSON.stringify(NDarr))
NDarr[0][1][2][3] = "kitty"; //access any location and change.
console.log(JSON.stringify(NDarr))
Reason For Anwser
There are good answers here but as JavaScript has changed here is an additional method of tackling this problem with some of the updated features in JavaScript.
function nArray (dem, size=dem, fill=null, currDepth=0) {
const arr = new Array(size).fill(fill);
return (currDepth+1 === dem) ? arr : arr.map(i => nArray(dem, size, fill, currDepth+1));
};
Notes
dem is the dimensions of the array.
size is the size of each dimension by default it is the dem value.
fill is the value that will be the default filled value.
currDepth is not to be used it is for the recursive nature of the function.
Create n dimensional matrix array with default values
function arr (arg, def = 0){
if (arg.length > 2){
return Array(arg[0]).fill().map(()=>arr(arg.slice(1)));
} else {
return Array(arg[0]).fill().map(()=>Array(arg[1]).fill(def));
}
}
//simple usage -> fills with 0
var s = arr([3,5,8,4]) // 4 dimensions
var t = arr([5,7]) // 2 dimensions
//fill with null
var k = arr([4,7,9] , null) // 3 dimensions
If you need to create 4d Array with index from 0 to 4 in the each cluster just do this code:
function createNDimArray(dimensions) {
if (dimensions.length > 0) {
var dim = dimensions[0];
var rest = dimensions.slice(1);
var newArray = new Array();
for (var i = 0; i < dim; i++) {
newArray[i] = createNDimArray(rest);
}
return newArray;
} else {
return undefined;
}
}
var MyArray=createNDimArray([5, 5, 5, 5]);
//returns a 5x5x5x5 array with index from 0 to 4;
MyArray[4][4][4][4]="MyArray 4d MyValue";
alert(MyArray[4][4][4][4]);
//For 5-demension array with this param.: 5x4x3x2x2 -> do this:
var MyArray_5d=createNDimArray([5, 4, 3, 2, 2]);
MyArray_5d[4][3][2][1][1]="MyArray 5d MyValue";
alert(MyArray_5d[4][3][2][1][1]);
MULTIDIMENSIONAL ARRAYS can be seen as EMBEDED ARRAYS.
See if the following can help.
<script type="text/javascript">"use strict";
const arr = [
["D1","D2","D3"],
[
["T11","T12","T13"],
["T21","T22","T23"]
]
];
for(let k=0;k<arr[0].length;k++)console.log(arr[0][k]);
// D1
// D2
// D3
for(let k=0;k<arr[1].length;k++)console.log(arr[1][k]);
// Array(3) [ "T11", "T12", "T13" ]
// Array(3) [ "T21", "T22", "T23" ]
for(let k=0;k<arr[1].length;k++)console.log(arr[1][0][k]);
// T11
// T12
for(let k=0;k<arr[1].length;k++)console.log(arr[1][1][k]);
// T21
// T22
for(let k=0;k<arr[1][0].length;k++)console.log(arr[1][0][k]);
// T11
// T12
// T13
for(let k=0;k<arr[1][1].length;k++)console.log(arr[1][1][k]);
// T21
// T22
// T23
</script>
// // // // // // // // // //
// // // // // // // // // //
And from the same point of vue, a MULTIDIMENSIONAL OBJECT !
<script type="text/javascript">"use strict";
const o = {
un:{u1:"U1",u2:"U2",u3:"U3"},
deux:{
trois : {d11:"D11",d12:"D12",d13:"D13"},
quatre: {t21:"T21",t22:"T22",t23:"T23"}
}
};
let ref = Object.keys(o);
for(let k=0;k<ref.length;k++)
console.log(ref[k] , ":" ,
Object.values(o)[k]);
// un : Object { u1: "U1", u2: "U2", u3: "U3" }
// deux : Object { trois: {…}, quatre: {…} }
// quatre: Object { t21: "T21", t22: "T22", t23: "T23" }
// trois : Object { d11: "D11", d12: "D12", d13: "D13" }
ref = Object.keys(o["un"]);
for(let k=0;k<ref.length;k++)
console.log(ref[k] , ":" ,
Object.values(o["un"])[k]);
// u1 : U1
// u2 : U2
// u3 : U3
ref = Object.keys(o["deux"]);
for(let k=0;k<ref.length;k++)
console.log(ref[k] , ":" ,
Object.values(o["deux"])[k]);
// trois : Object { d11: "D11", d12: "D12", d13: "D13" }
// quatre : Object { t21: "T21", t22: "T22", t23: "T23" }
ref = Object.keys(o["deux"]["trois"]);
for(let k=0;k<ref.length;k++)
console.log(ref[k] , ":" ,
Object.values(o["deux"]["trois"])[k]);
// d11 : D11
// d12 : D12
// d13 : D13
ref = Object.keys(o["deux"]["quatre"]);
for(let k=0;k<Object.keys(ref).length;k++)
console.log(ref[k] , ":" ,
Object.values(o["deux"]["quatre"])[k]);
// t21 : T21
// t22 : T22
// t23 : T23
ref = Object.keys(o["deux"]["trois"]);
console.log(ref[0] , ":" ,
Object.values(o["deux"]["trois"])[0]);
// d11 : D11
ref = Object.values(o["deux"]["quatre"]);
console.log(Object.keys(o["deux"]["quatre"])[ref.length-1] ,
":" , ref[ref.length-1] );
// t23 : T23
</script>

How do I avoid looping through an array to find a partial match?

I am looping through an array of english phrases, and if i find a match, with the current text node, i replace it with it's translation in the non_english array. All of that works 100% for exact matches.
But for partial matches, I need to use the .match command, which allows for partial matches.
My code to search for exact matches is like this:
var found = $.inArray(value,en_lang);
Then if there is a found value, then do replacement of text. This method is fast and I love it.
However to do partial word/phrase matching, I have to use this looping code.
// loop thru language arrays
for (var x = en_count; x > 0; x--) {
// assign current from/to variables for replace
var from = en_lang[x];
var to = other_lang[x];
// if value match do translation
if (value.match(from)) {
content(node, value.replace(from, to));
}
// mark this node as translated
if ($.browser.msie == 'false') {
$(node).data('translated', 'yes');
}
}
This does the job but is pretty slow. After a lot of research, I have found that I can convert the english array to a list-based string via the join command.
But I am unable to come up with a function to search this list for a partial match, and return the position in the list.
I was trying out this old js function created in 2006. But I can't figure out how to get the position back, correctly.
function listfind(list, value, delimiters) {
if (!delimiters) {
var delimiters = ','
}
_TempListSplitArray = list.split(delimiters)
var FoundIdx = 0;
for (i = 0; i < _TempListSplitArray.length; i++) {
if (_TempListSplitArray[i] == value) {
FoundIdx = i + 1;
break
}
if (value.match(_TempListSplitArray[i])) {
FoundIdx = i + 1;
break
}
}
return FoundIdx
}
Thank you for your time.
Javascript has a foreach type of system but its still based on a loop
var array = ['hello', 'world'];
for(var key in array){
alert(array[key]);
}
Thats the best your getting for looping though an array but this way allso works with objects
var obj = {'one':'hello', 'two':'world'];
for(var key in obj){
alert("key: "+key+" value: "+obj[key]);
}
UPDATED for Comments on your question
You can just replace the text you know
var str = "hello World";
str = str.replace("hello", "Bye bye");
alert(str);

Can anyone see what is wrong with my Javascript?

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;

Categories

Resources