This question already has an answer here:
Escape string for use in Javascript regex [duplicate]
(1 answer)
Closed 17 days ago.
In my web page I have a "find" feature, where the user types in some text in "find" dialog and it gets the index of where the text can be found in a variable. In advance I know neither the text that will be searched, nor the text the user will be looking for. I provide them an option for whether to match case, and whether to find only whole words (e.g. whether "managers" should be a match if they enter "manager".
The following code is a stripped down version of my code with just what is relevant to my issue. In this example, I want to look for "(1)" in "This is a test.(10)". My expectation after execution is that index will be -1, but it is 16, which is the index of the "1".
Can you tell me why this doesn't work and what would work? Thanks.
let matchCase = false;
let wholeWord = false;
let index = 0;
let options = "";
let phrase = "(1)";
phrase = phrase.replaceAll(String.fromCharCode(160), "\\s");
if (!matchCase) options += "i";
if (wholeWord) phrase = "\\b" + phrase + "\\b";
let regex = new RegExp(phrase, options);
let text = "This is a test.(10)";
let index = text.search(regex);
console.log(index);
You need to escape regular expression metacharacters like ( in the input.
//Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
let matchCase = false;
let wholeWord = false;
let options = "";
let phrase = escapeRegExp("(1)");
phrase = phrase.replaceAll(String.fromCharCode(160), "\\s");
if (!matchCase) options += "i";
if (wholeWord) phrase = "\\b" + phrase + "\\b";
let regex = new RegExp(phrase, options);
let text = "This is a test.(10)";
let index = text.search(regex);
console.log(index);
Related
In this problem, I would like to find the number of distinct characters (case-insensitive).
I understand there are other approaches to the problem, but my current approach is to identify the first character in the text string and remove all equivalent characters globally, +1 to the counter and rinse and repeat for all remaining chars. Looking at the JS docs online, I can't seem to figure out how to make this work, I figured someone could teach me how to do the regular expression for this. Thanks.
let text = "aAabbbacccaaade";
text = text.replace(text[0]/gi,"");
// text = text.replace(/text[0]/gi,""); => aAabbbacccaaade
// text = text.replace(text[0]/gi,""); => gi is undefined error.
Create your regex using the new constructor and a string argument:
let text = "aAabbbacccaaade";
console.log(text);
let regex = new RegExp(text[0], "gi");
text = text.replace(regex,"");
console.log(text);
Looping this should work for your method:
const text = "aAabbbacccaaade";
function countUnique(str) {
let mutableStr = str;
let count = 0;
while (mutableStr.length > 0) {
let r = new RegExp(mutableStr[0], "gi");
mutableStr = mutableStr.replace(r, "");
count++;
}
return count;
}
console.log(countUnique(text));
I am trying to capture the counts associated with the keywords in the string txt. All the keywords are loaded into an array ahead of time.
This code is in jquery/javascript. I cannot hard code string keywords so that is why they are stored in an array. Please assist me in finding what goes in place of "Reg Expression" before and/or after the keyword variable within the loop.
The html br can be used to end that regexmatch in that iteration of the loop.
Trying to end up with keywordCount = "2, 5, 11"
//String I need to search through
var txt = "Edit Req'd2<br>Errors5<br>Pndg App11<br>";
//array of keywords I can use to find associated counts to keywords
var keyword = ["Edit Req'd", "Errors", "Pndg App"];
//empty string declared before loop
var keywordCount = '';
for (i = 0; i < keyword.length; i++) {
// takes the comma off end of first entry in array
// might not be needed or another method might be better?
keyword[i] = $.trim(keyword[i]);
//regex expression generated using keyword and unknown expression
var regexmatch = RegExp("Reg Expression" + keyword + "Reg Expression")
//use regex expression to generate string containing counts
keywordCount += (txt.match(regexmatch)) + ",";
}
Here is the example which may helps you in achieving your required output.
//String I need to search through
var txt = "Edit Req'd2<br>Errors5<br>Pndg App11<br>";
//array of keywords I can use to find associated counts to keywords
var keyword = ["Edit Req'd", "Errors", "Pndg App"];
//empty string declared before loop
var keywordCount = '';
var i = 0;
var keywordCount = "";
var splittedValue = "";
while (i < keyword.length) {
if (txt.indexOf(keyword[i]/i)) {
splittedValue = txt.split(keyword[i]);
if (keywordCount === "") {
keywordCount = splittedValue[1].split("<br>")[0];
} else {
keywordCount += ", " + splittedValue[1].split("<br>")[0];
}
}
i += 1;
}
console.log(keywordCount);
I would use a digit/numeric range to match the number ([0-9]; this is pretty basic regex stuff), and use a group to match any of the keywords:
Any number of digits: [0-9]+
Any of your keywords: (something|somethingelse|other)
You can use capture-groups as well to have match() return them separately:
var keyword = ["Edit Req'd", "Errors", "Pndg App"];
var regexmatch = RegExp('(\b' + keyword.join('|') + ')([0-9]+)', 'g')
(note that we use the word-boundary \b to make sure keyword is not part of a longer word, and the 'g' flag for global to signal we want multiple results)
Now, match() will only match one result, and we want matches for every keyword, so we’ll use exec() instead:
var txt = "Edit Req'd2<br>Errors5<br>Pndg App11<br>";
var keyword = ["Edit Req'd", "Errors", "Pndg App"];
var regex = RegExp('(\b' + keyword.join('|') + ')([0-9]+)', 'g')
var match = regex.exec( txt ); // ...find the first match
var numbers = [];
while ( match !== null ) {
numbers.push( match[ 2 ]); // #0 of exec() its return-value is the result as a whole: "Edit Req'd2"
// #1 is the value of the first capture-group: "Edit Req'd"
// #2 is the value of the second capture-group: "2"
match = regex.exec( txt ); // ...find the next match
}
console.log("the numbers are:", numbers);
Lastly, do note that regular expressions may look cool, they are not always the fastest (performance-wise). If performance matters a lot, you could use (for example) indexOf() instead.
From your question it seems like you could brush up on your knowledge of regular expressions a little bit. There’s a ton of articles around (just search for “regular expressions basics” or “regex 101”) – like this one:
https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285*
I have the generic fuzzy search right now, so that if type "a" it'll return me every word that contains an A. However I want a more refined search that does this.
For example I have the word: 'Frankster Muniz'
searching "frank","fr","f", "mun", "m" will indeed return 'Frankster Muniz'
searching "rank","ster","r", "niz" will not return anything
it must match the first beginning words,I have no idea where to start here. I am very new to regex. Thank you
You could begin with this:
If input is user-input and name is name on database ,
var name = "Frankster Muniz";
var input = "Frank";
function match(name,input){
var matched = 0;
if(name.match(new RegExp("\\b"+input+".*","i")))
matched=1;
return matched;
}
console.log(match(name,"Frank"));
console.log(match(name,"ster"));
You can start matching at the beginning of words by using the word boundary character \b. So the power of the regex becomes:
new RegExp(`\\b${input}`, 'i');
Check out the interactive example:
let names = [
'Frankster Muniz',
'Sarah Walin',
'Tyler Robinson',
'Ronald Muniz'
];
let results = document.querySelector('#results');
let input = document.querySelector('input');
input.addEventListener('input', function() {
findUsers(this.value);
});
buildList(names);
function findUsers(input) {
let reg = new RegExp(`\\b${input}`, 'i');
let found = names.filter(name => reg.test(name));
buildList(found);
}
function buildList(names) {
let html = '';
names.forEach(name => html += `<li>${name}</li>`);
results.innerHTML = html;
}
<label>Filter:</label>
<input id="search">
<br><br>
<div>Names:</div>
<ul id="results"></ul>
I'm facing some problem while trying to send text to some spelling API.
The API return the corrections based on the words index, for example:
sentence:
"hello hoow are youu"
So the API index the words by numbers like that and return the correction based on that index:
0 1 2 3
hello hoow are youu
API Response that tell me which words to correct:
1: how
3: you
On the code I using split command to break the sentence into words array so I will be able to replace the misspelled words by their index.
string.split(" ");
My problem is that the API trim multiple spaces between words into one space, and by doing that the API words index not match my index. (I would like to preserve the spaces on the final output)
Example of the problem, sentence with 4 spaces between words:
Hello howw are youu?
0 1 2 3 4 5 6 7
hello hoow are youu
I thought about looping the words array and determine if the element is word or space and then create something new array like that:
indexed_words[0] = hello
indexed_words[0_1] = space
indexed_words[0_2] = space
indexed_words[0_3] = space
indexed_words[0_4] = space
indexed_words[0_5] = space
indexed_words[0_6] = space
indexed_words[0_7] = space
indexed_words[1] = how
indexed_words[2] = are
indexed_words[3] = you?
That way I could replace the misspelled words easily and than rebuild the sentence back with join command but the problem but the problem that I cannot use non-numeric indexes (its mixed up the order of the array)
Any idea how I can keep the formatting (spaces) but still correct the words?
Thanks
in that case you have very simple solution:L
$(document).ready(function(){
var OriginalSentence="howw are you?"
var ModifiedSentence="";
var splitstring=OriginalSentence.split(' ')
$.each(splitstring,function(i,v){
if(v!="")
{
//pass this word to your api and appedn it to sentance
ModifiedSentence+=APIRETURNVALUE//api return corrected value;
}
else{
ModifiedSentence+=v;
}
});
alert(ModifiedSentence);
});
Please review this one:
For string manipulation like this, I would highly recommend you to use Regex
Use online regex editor for faster try and error like here https://regex101.com/.
here I use /\w+/g to match every words if you want to ignore 1 or two words we can use /\w{2,}/g or something like that.
var str = "Hello howw are youu?";
var re = /\w+/g
var words = str.match(re);
console.log("Returning valus")
words.forEach(function(word, index) {
console.log(index + " -> " + word);
})
Correction
Just realize that you need to keep spacing as it is, please try this one:
I used your approach to change all to space. create array for its modified version then send to your API (I dunno that part). Then get returned data from API, reconvert it back to its original formating string.
var ori = `asdkhaskd asdkjaskdjaksjd askdjaksdjalsd a ksjdhaksjdhasd asdjkhaskdas`;
function replaceMeArr(str, match, replace) {
var s = str,
reg = match || /\s/g,
rep = replace || ` space `;
return s.replace(reg, rep).split(/\s/g);
}
function replaceMeStr(arr, match, replace) {
var a = arr.join(" "),
reg = match || /\sspace\s/g,
rep = replace || " ";
return a.replace(reg, rep);
}
console.log(`ori1: ${ori}`);
//can use it like this
var modified = replaceMeArr(ori);
console.log(`modi: ${modified.join(' ')}`);
//put it back
var original = replaceMeStr(modified);
console.log(`ori2: ${original}`);
Updated
var str = "Hello howw are youu?";
var words = str.split(" ");
// Getting an array without spaces/empty values
// send it to your API call
var requestArray = words.filter(function(word){
if (word) {
return word;
}
});
console.log("\nAPI Response that tell me which words to correct:");
console.log("6: how\n8: you");
var response = {
"1": "how",
"3": "you"
}
//As you have corrected words index, Replace those words in your "requestArray"
for (var key in response) {
requestArray[key] = response[key];
}
//now we have array of non-empty & correct spelled words. we need to put back empty (space's) value back in between this array
var count = 0;
words.forEach(function(word, index){
if (word) {
words[index] = requestArray[count];
count++;
}
})
console.log(words);
Correct me, if i was wrong.
Hope this helps :)
Try this JSFiddle
, Happy coding :)
//
// ReplaceMisspelledWords
//
// Created by Hilal Baig on 21/11/16.
// Copyright © 2016 Baigapps. All rights reserved.
//
var preservedArray = new Array();
var splitArray = new Array();
/*Word Object to preserve my misspeled words indexes*/
function preservedObject(pIndex, nIndex, title) {
this.originalIndex = pIndex;
this.apiIndex = nIndex;
this.title = title;
}
/*Preserving misspeled words indexes in preservedArray*/
function savePreserveIndexes(str) {
splitArray = str.split(" ");
//console.log(splitArray);
var x = 0;
for (var i = 0; i < splitArray.length; i++) {
if (splitArray[i].length > 0) {
var word = new preservedObject(i, x, splitArray[i]);
preservedArray.push(word);
x++;
}
}
};
function replaceMisspelled(resp) {
for (var key in resp) {
for (var i = 0; i < preservedArray.length; i++) {
wObj = preservedArray[i];
if (wObj.apiIndex == key) {
wObj.title = resp[key];
splitArray[wObj.originalIndex] = resp[key];
}
}
}
//console.log(preservedArray);
return correctedSentence = splitArray.join(" ");
}
/*Your input string to be corrected*/
str = "Hello howw are youu";
console.log(str);
savePreserveIndexes(str);
/*API Response in json of corrected words*/
var apiResponse = '{"1":"how","3":"you" }';
resp = JSON.parse(apiResponse);
//console.log(resp);
/*Replace misspelled words by corrected*/
console.log(replaceMisspelled(resp)); //Your solution
This question already has answers here:
Split string once in javascript?
(17 answers)
Closed 8 years ago.
I know there are several ways to split an array in jQuery but I have a special case:
If I have for example this two strings:
"G09.4 What"
"A04.3 A new Code"
When I split the first by ' ' I can simply choose the code in front with [0] what would be G09.4. And when I call [1] I get the text: What
But when I do the same with the second string I get for [1] A but I want to retrieve A new Code.
So how can I retrieve for each string the code and the separate text?
Use
var someString = "A04.3 A new Code";
var index = someString.indexOf(" "); // Gets the first index where a space occours
var id = someString.substr(0, index); // Gets the first part
var text = someString.substr(index + 1); // Gets the text part
You can split the string and shift off the first entry in the returned array. Then join the leftovers e.g.
var chunks = "A04.3 A new Code".split(/\s+/);
var arr = [chunks.shift(), chunks.join(' ')];
// arr[0] = "A04.3"
// arr[1] = "A new Code"
Instead of splitting the string on the space, use a combination of indexOf and slice:
var s = "A04.3 A new Code";
var i = s.indexOf(' ');
var partOne = s.slice(0, i).trim();
var partTwo = s.slice(i + 1, s.length).trim();
You can use match() and capture what you need via a regular expression:
"G09.4 What".match(/^(\S+)\s+(.+)/)
// => ["G09.4 What", "G09.4", "What"]
"A04.3 A new Code".match(/^(\S+)\s+(.+)/)
// => ["A04.3 A new Code", "A04.3", "A new Code"]
As you can see the two items you want are in [1] and [2] of the returned arrays.
What about this one:
function split2(str, delim) {
var parts=str.split(delim);
return [parts[0], parts.splice(1,parts.length).join(delim)];
}
FIDDLE
Or for more performance, try this:
function split2s(str, delim) {
var p=str.indexOf(delim);
if (p !== -1) {
return [str.substring(0,p), str.substring(p+1)];
} else {
return [str];
}
}
You can get the code and then remove it from the original string leaving you with both the code and the string without the code.
var originalString = "A04.3 A new Code",
stringArray = originalString.split(' '),
code,
newString;
code = stringArray[0];
newString = originalString.replace(code, '');