Javascript: How to compare to sentences word to word - javascript

I'm sort of creating typing tutor with custom options.
Not a professional (don't get mad at me for being wrong-person-wrong place) but thanks to helpful forums like stackoverflow.com and contributing traffic/people I'm able to pull it out in a day or two.
Directly now, here!
while (i < len+1){
if(boxarray[i] == orgarray[i]){
++i;
actualScore = i - 1;
}
I've searched already, '==' operator is of no use, I will not go for JSON.encode. I met similar solution at this page . But in my case I've to loop through each word while comparing two sentences. Detail is trivial, if someone please help me solve above, I won't return with complain on the same project, promise.
Okay I'm putting more code if it can help you help me.
var paratext = document.getElementById('typethis').innerHTML;
var orgstr = "start typing, in : BtXr the yellow box but. please don't shit." ;
var boxtext = document.getElementById('usit').value;
var endtrim = boxtext;
var actualScore;
var orgarray = listToArray(orgstr," ");
var boxarray = listToArray(boxtext," ");
var len = boxarray.length;
var i = 0;
var actualScore; //note var undefined that's one mistake I was making [edit]
if(orgstr.indexOf(boxtext) !== -1){
while (i < len+1){
if(boxarray[i] == orgarray[i]){
++i;
actualScore = i - 1;
}
}
alert(actualScore);
}

If I follow what you're after how about something like this:
http://jsfiddle.net/w6R9U/
var s1 = 'The dog sleeps';
var s2 = 'the dog jogs';
var s1Parts= s1.split(' ');
var s2Parts= s2.split(' ');
var score = 0;
for(var i = 0; i<s1Parts.length; i++)
{
if(s1Parts[i] === s2Parts[i])
score++;
}
"The dog sleeps" and "the dog sleeps" results in a score of 2 because of case (which could be ignored, if needed). The example above results in a score of 1. Could get a percent by using the length of the sentences. Hope this helps! If nothing else might get you started.

The following will compare each individual character, decreasing the "actualScore" for each inequality:
http://jsfiddle.net/ckKDR/
var sentence1 = "This is the original sentence.", // original text
sentence2 = "This is teh originel sentence.", // what the user typed
length = sentence1.length,
actualScore = length, // start with full points
i = 0;
while(i<length){
if(sentence1[i]!==sentence2[i]){
actualScore--; // subtract 1 from actual score
}
i++; // move to the next index
}
alert("'sentence2' is "+Math.round(100*(actualScore/length))+"% accurate");

Let's say the input is your two sentences as strings.
Then the first thing to do is to create two temporary strings, with all the non-word characters eliminated (e.g. punctuation characters). Split the sentences into string arrays by word delimiters.
Then you can assign an integer variable to score. Create an outer loop and an inner loop for the two sentences. When the words match in the sentences, increment the variable by 1, remove the word from the 2nd sentence (replace the word with a non-word character) and break out of the inner loop.
Also, use this operator for word comparison instead:
===

Your problem is
if (boxarray[i] = orgarray[i])
The single = is the assignment operator. Replace it with
===
to be a comparison.

You are not comparing you are assigning
if(boxarray[i] = orgarray[i]){
^^^
So it will be true on each iteration. Fix the typo to actually perform the check you want
if(boxarray[i] === orgarray[i]){
^^^
And how you are calculating the score looks to be wrong. You should be doing something like
var score = orgstr.length;
while...
if(boxarray[i] === orgarray[i]){
score--;
}

{
string1="string1";
string2="string2 is here";
changepercent(string1,string2);
}
function changepercent(string1,string2) {
var s1Parts= string1.split(' ');
var s2Parts= string2.split(' ');
var matched = 0;
for(var i = 0; i<s1Parts.length; i++)
{
for(var j = 0; j<s2Parts.length; j++)
{
if(s1Parts[i] === s2Parts[j])
matched++;
}
}
var percentage=(matched/Math.max(s1Parts.length, s2Parts.length))*100;
  console.log(matched);
console.log(percentage);
if(percentage<50)
{
console.log("Change Above 50%");
}
}
Slightly modified first code

Related

How do I mask an email address between the first and the last character before the # sign?

My goal is to edit the string (which has an email) to mask the first part, like say the email is johndoe#abc.com then I should output j*****e#abc.com.
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first[i] = '*';
}
ans = first +"#" +parts[1];
}else{
}
return ans;
};
However in my loop I can't change the characters to asterisks.
After execution I see value of first still same as parts[0] and has no asterisks, can some one explain why? Also, what would I need to do to modify the variable inside loop?
To answer your question... javascript allows you access values of a string using [] indexing.. but that is read only access... you cannot insert/replace values using that operator.
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
When using bracket notation for character access,
attempting to delete or assign a value to these properties will not succeed.
The properties involved are neither writable nor configurable.
(See Object.defineProperty() for more information.)
You need to extract the values you want to keep from the existing string and build up a new string as noted in other answers...
Well, this's what you're looking for, and this will be the output j*****e#abc.com.
var ans = "";
var S = "johndoe#abc.com"; //example
S = S.toLowerCase();
var parts = S.split("#");
var first = "";
for(var i = 0; i < parts[0].length; i++){
if(i != 0 && i != parts[0].length - 1){
first += '*';
}else{
first += parts[0][i];
}
}
ans = first +"#"+ parts[1];
console.log(ans);
Here is the code with your approach:
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0][0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first += '*';
}
ans = first + parts[0][parts[0].length - 1] +"#" +parts[1];
}else{
}
return ans;
};
But if i were you i would use:
var mail = "johndoe#abc.com";
mail = mail.replace(/(?<=.)(.+?)(?=.#)/gi, '*'.repeat(mail.split('#')[0].length - 2));
console.log(mail);
You can use the bracket notation on a string (like an array) to get the character at a specific index, but you can't use this to change characters. So first[i] = '*' in your code wont do anything.
Strings in JavaScript are immutable. This means that if you want to change a string, a new string instance will be created. This also means that when you change a string in a for-loop, it can impact performance. (Although in this case the difference wont be noticeable.
)
I would use this code:
function maskPII(str) {
const indexOfAt = str.indexOf('#');
if (indexOfAt <= 2) {
return str;
}
return str[0] + '*'.repeat(indexOfAt - 2) + str.substring(indexOfAt - 1);
}
const email = 'johndoe#abc.com';
console.log(email);
console.log(maskPII(email));
It will look for the index of the # sign. If the index is less or equal than 2, (when not found the index will be -1) it will return the original string.
Otherwise it will get the first character, calculate the amount of asterisks needed (index of the # sign -2) and repeat those and then add the rest of the original string.

Search for string between two characters if next to a specific string

I am in need of some modification to my function to allow for a search of two strings on one line of a value. I am trying to work through this on my own but I need some help. Here is an example of a cell value being looked at. Assume there are no leading or trailing newlines. Also, all the cells have the same format. same number of lines, same structure of membertype: last, first etc.
Say I want to see if this cell contains a team lead with the name of last2 or a Manager with the name first4. Both the type of employee and name would be user inputted.
I tried using the following that I created with the help of this.
indexOf(':(.*):')
It returns the position of the content between and including the colons. Then I tried the following:
flatUniqArr[0].search('Supervisor:')
This is where I'm stuck. It returns the index to the last digit of the first line.
My thought was to do a search of the user inputted name between the colons if they follow the user inputted member type. How can I accomplish this?
Clarifications:
The end goal is to verify that the name and member type are on the same line and excluded from an array I am building for .setHiddenValues(). So if they are on the same line exclude from list.
Here is the function I will be adding it to:
var flatUniqArr = colValueArr.map(function(e){return e[0].toString();})
.filter(function(e,i,a){
return (a.indexOf(e) == i && !(visibleValueArr.some(function(f){
return e.search(new RegExp(f,'i')) + 1;
})));
});
return flatUniqArr;
Where flatUniqArr is the list of hidden values. colValueArr is the array of values from a column. visibleValueArr is the name which is user inputted and memberType will be the member type.
Attempts using Liora's solution: (Updated... Works now)
var flatUniqArr = []
var lines = []
Logger.log(visibleValueArr)
Logger.log(memberType)
for (var i = 0; i < colValueArr.length; i++){
lines = colValueArr[i].toString().split('\n');
var found = false;
for(var j = 0; j < lines.length; j++){
var data = lines[j].toLowerCase().split(':')
if(data[0] == memberType.toString().toLowerCase() && data[1].indexOf(visibleValueArr.toString().toLowerCase()) != -1){
found = true;
}
}
Logger.log(found)
if(found == false){flatUniqArr.push(colValueArr[i])}
}
return flatUniqArr;
It works now. It seems like a lot of code though. I'd be open to alternative solutions if they are faster and/or less lines of code.
Updated: Added .toString().toLowerCase() as the user may input lowercase values.
I assume all the line have this format.
If you split each line with the separator ":"
var array = value.split(":")
Then you'd have
array[0] //the current role
array[1] //the list of name
array[2] //the email
And you can check each names then
if(array[0] == "Team Lead" && array[1].indexOf("last2") != -1)
An example with a linesplit:
var lines = value.toString().split("\n");
var found = false;
for(var i = 0; i < lines.length ; i++){
var data = value.split(":")
if(data[0] == "Team Lead" && data[1].indexOf("last2") != -1){
found = true;
}
}
How about just building the regex using the user input?
function search(line, employeeType, employeeName) {
var regexp = '/' + employeeType + ': ' + employeeName + '/'
return line.search(regexp)
}
Or better yet, if it always occurs at the beginning of the string, just use startsWith()

Function behaves strangely after first onclick

I have the following HTML:
<input type = "text" id = "pick"> <input type = "submit" value = "Submit" onclick = "guessWord()">
That runs my js function which works fine (with unrelated hiccups) on the first call. But if I change my text and submit it again without reloading my initial if/else statement behaves incorrectly. Specifically, the if/else is supposed to check if the user inputted word is in an array. It works properly on the first call, but after that it jumps to the else block even when it shouldn't.
Here is the js (apologies in advance for including the whole function, I'm just usually asked to include more code than I initially do):
function guessWord() {
var comWords, match, compWord = "";
var possWords = dictFive;
var firstFive = ["vibex", "fjord", "nymph", "waltz", "gucks"]; // note: right now choosing any of these words results in unexpected behavior -- either it doesn't accept them or it freezes.
var inputWord = document.getElementById("pick").value.toLowerCase().replace(/\s+/g, '');
if (possWords.includes(inputWord)) { // checks to see if the user inputted word is in our dictionary.i f not, requests a different word.
// start game loop:
// in order to try and get as much information as possible in the first few turns I start by guessing the five words in firstFive[]: vibex, fjord, nymph, waltz, gucks. together, these words give us information about 25 letters.
for (let d = 0; d < inputWord.length; d++) { // this loop will run for the length of the inputted word, making it scaleable so in the future the program could accept shorter or longer words. within the current scope it will always be 5.
compWord = firstFive[d]; // the computers word will loop through each word in firstFive[].
if (inputWord === compWord) { // if the word matches the user inputted word:
document.getElementById("otpt").innerHTML = "Your word was: " + firstFive[d] + ". I guessed it in " + (d + 1) + " turns.";
return;
} else { // if the word is not the user inputted word, then:
comWords = (inputWord + compWord).split('').sort().join(''); // we combine the users word with the comps word and sort them by character.
match = comWords.length - comWords.replace(/(\w)\1+/g, '$1').length; // match produces a numerical value for how many letters matched between both words.
for (let e = 0; e < possWords.length; e++) { // loop to cycle through our dictionary.
for (let f = 0; f < inputWord.length; f++) { // loop to cycle through all the different match options.
if (match === 0) { // if there are no matches we can:
if (possWords[e].includes(firstFive[f])) { // go through the dict and get rid of every word that has letters in common with the word.
possWords.splice(e, 1);
}
} else if (match === f) { // if there's at least one letter in common:
comWords = (possWords[e] + compWord).split('').sort().join(''); // as we cycle through the dict, pick each available word, combine and sort with the chosen word,
var matchFive = comWords.length - comWords.replace(/(\w)\1+/g, '$1').length; // and then find how many letters match.
if (matchFive != match) { // any words in dict that have a different match value can be deleted.
possWords.splice(e, 1);
}
}
}
}
}
}
// once we've worked through the words in firstFive[] we start guessing randomly.
for (let a = 0; a < possWords.length; a++) { // the loop max is set to the length of the array because that's the maximum amount of time the guessing can take.
compWord = possWords[Math.floor(Math.random() * possWords.length)]; // choose a random word.
if (compWord === inputWord) { // check if the random word is the inputted word. if it is:
document.getElementById("otpt").innerHTML = "Your word was: " + compWord + ". I guessed it in " + (a + 5) + " turns. I had " + possWords.length + " remaining words that were possible matches.";
return;
} else { // while the word still isn't correct:
comWords = (compWord + inputWord).split('').sort().join(''); // again, we join and sort it.
match = comWords.length - comWords.replace(/(\w)\1+/g, '$1'); // find its match value.
for (let c = 0; c < inputWord.length; c++) { // loop through inputted word's length to check all letters.
if (match === 0) { // again, no matches we can safely delete all words with those letters.
if (possWords.includes(compWord[c])) {
possWords.splice(c, 1);
}
} else if (match === c) { // if match is higher than 0:
for (let g = 0; g < possWords.length; g++) {
comWords = (possWords[g]+ compWord).split('').sort().join('');
matchAll = comWords.length - comWords.replace(/(\w)\1+/g, '$1');
if (match != matchAll) {
possWords.splice(g, 1);
}
}
}
}
}
}
} else { // If the user inputted word was not in our dictionary, requests a different word:
document.getElementById("otpt").innerHTML = "Please choose a different word.";
}
}
(For context, dictFive is an array located on a separate file.) The code is trying to guess the user inputted word by checking how many letters match and then splicing out words from the master array if they can't match, so the array possWords starts with about 2500 words and gets narrowed down to a few hundred by the end of the function. As far as I can tell, the function should be resetting the vars properly every time it's called, though, but I'm guessing it isn't for some reason?
Your dictFive array is being spliced each time the function is called.
When you set possWords = dictFive, and then splice possWords later, you're also splicing dictFive because both variables refer to the same array. Then, the second time the function is run, dictFive is still in its spliced state. Instead of setting possWords = dictFive, try making a copy of the array. That way, you'll splice the copy without affecting the original, dictFive. You can clone an array by possWords = dictFive.slice().
var dictFive = [0,1,2,3,4]; // Just an example of whatever dictFive might be
var possWords = dictFive; // This makes possWords refer to the same thing as dictFive
possWords.splice(0, 1); // Splicing the array at whatever point
possWords // [1,2,3,4] because the 0th element was spliced out
dictFive // also [1,2,3,4] because both dictFive and possWords are the same array
compare that to
var dictFive = [0,1,2,3,4];
var possWords = dictFive.slice(); // This makes a copy of the array instead of referencing the original dictFive
possWords.splice(0, 1);
possWords // [1,2,3,4];
dictFive // Now, this array is still [0,1,2,3,4] because only the possWords array was spliced. dictFive wasn't affected.

Regex for a word that repeats only the chars i provide?

Ok so what im trying to do is match words like "lol" and "lollll" and "llllol" and "llllooooollll" and "loool" but not "pfftlol" or "lolpfft" etc.
my current code is
_.each(req.room._settings.automod.cussing.words, function(word)
{
if(req.message.text.match(new RegExp('\\b'+word.split('').join('+?')+'\\b', 'gi')))
{
if(req.user && req.user.cache.automod.cussing === 0)
{
req.user.cache.automod.cussing = 1;
req.write(req.user.name+", Please refrain from cussing in your messages this is your first and only warning next time you will be deleted.");
req.room.delLastUser(req.user.name, 1);
}
else
{
req.room.delLastUser(req.user.name, 1);
}
}
});
and out of it
req.message.text.match(new RegExp('\\b'+word.split('').join('+?')+'\\b', 'gi'))
also lets say that req.room._settings.automod.cussing.words is ['lol','what'] since i dont want to list actual cuss words
and req.message.text is 'hah lollll hey'
also this is going through an _.each statement or foreach
I'm using NodeJS
right now it returns the word as long as it partially matches
anyone know what I'm doing wrong?
The answer from Ismael Miguel is correct
/\b(l)+(o)+(l)+\b/
which looks like this in my code
var reg = '\\b('+cuss.split('').join(')+(')+')+\\b';
req.message.text.match(new RegExp(reg, 'gi'));
Try this regex:
/.*\b(l+o+l+)\b.*/
var strings = ["who is lol", "looolll am i", "rofl llllooll", "pfftlol", "lolwho", "anotherlol", "lllllol hehe"];
for(var i = 0; i < strings.length; ++i){
var match = strings[i].match(/.*\b(l+o+l+)\b.*/);
if (match)
document.write( match[0] + "<br>") ;
}

JavaScript Syllable Counter - Counting Per Line

Current
I’ve re-worked this syllable counter script to:
Get the value of textarea 1.
Count the number of syllables in textarea 1.
Display the results in textarea 2.
Update the count every time the value of textarea 1 is edited.
Act as a function (be able to run in multiple instances if wanted).
Example function of current code
Input (Textarea 1)
i would appreciate
any help
at all
Results (Textarea 2)
11
Current code
Here is the existing code as a JSFiddle.
Goal
I would like this script to:
Count the syllables of textarea 1 on a per line basis: presumably by splitting the textarea 1 value where there are line breaks e.g. .split('\n');.
Output the results, showing the total number of syllables counted per line.
Example function of desired code
Input (Textarea 1)
i would appreciate
any help
at all
Results (Textarea 2)
6
3
2
Problem
I’m quite stuck as to how to do this and would really appreciate any help or JSFiddle showing how to work with the existing code to achieve this.
Notes
For anyone who may be interested using in the syllable count function code itself: it’s not 100% accurate and fails on some words but gives a good general idea.
Try this and let me know if it's what you needed.
Callouts:
I created an array that spits the lines up stores them var arrayOfLines = $("[name=set_" + $input + "]").val().match(/[^\r\n]+/g);.
Then loop through that array and do exactly what you did before, but on each array entry. Then store the results in tempArr, and display the tempArr results.
See Fiddle
function $count_how_many_syllables($input) {
$("[name=set_" + $input + "]").keyup(function () {
var arrayOfLines = $("[name=set_" + $input + "]").val().match(/[^\r\n]+/g);
var tempArr = [];
var $content;
var word;
var $syllable_count;
var $result;
for(var i = 0; i < arrayOfLines.length; i++){
$content = arrayOfLines[i];
word = $content;
word = word.toLowerCase();
if (word.length <= 3) {
word = 1;
}
if (word.length === 0) {
return 0;
}
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
.replace(/^y/, '')
.match(/[aeiouy]{1,2}/g).length;
$syllable_count = word;
$result = $syllable_count;
tempArr.push($result);
}
$("[name=set_" + $input + "_syllable_count]").val(tempArr);
});
}
(function($) {
$count_how_many_syllables("a");
})(jQuery);

Categories

Resources