Check if a string contains a specific word only once - javascript

I am trying to check if a string contains a specific word only once.
Here is my attempt, but it's not working:
const test = "hello this is a new string hello";
// if hello contains only once then true otherwise false;
// here is my try but
let containshello = test.includes("hello");
console.log(containshello);

Here's an approach using filter
const containsWordOnce = (str, searchKey) => {
return str.split(' ').filter((word) => word === searchKey).length === 1;
};
const test = "hello this is a new string hello";
console.log(containsWordOnce(test, "hello"));

Use 'regex match' to get the occurrence of a substring in a string.
const test = "hello this is a new string hello";
console.log(test.match(/hello/gi)?.length); // 2 : 'hello' two times
console.log(test.match(/new/gi)?.length); // 1 : 'new' one time
console.log(test.match(/test/gi)?.length); // undefined : 'test' doesn't exist in string.
I have used 'g' for Global checking and 'i' for ignoring the case.
If you want to create 'Regex' object create like this:
const test = "hello this is a new string hello";
const regx = new RegExp('hello', 'gi') // /hello/gi
console.log(test.match(regex)?.length);

const test = "hello this is a new string hello";
const findString = "hello"
console.log(test.split(findString).length-1 === 1)

I would just use a regular expression and use the match method on the string you would like to search using the "i" and "g" flag. Below is an example function although there are most likely better ways.
function containsWordOnce(string, word) {
const re = new RegExp(word, 'ig');
const matches = string.match(re);
return matches.length === 1;
}
Just plug in your string and word your trying to find.

Related

Remove a substring to make given word in javascript

I want to know about the algorithm for below question in JavaScript.
Check whether the given word can be "programming" or not by removing the substring between them. You can only remove one substring from the given the word.
Give answer in 'yes' and 'no'
example answer explanation
"progabcramming" yes remove substring 'abc'
"programmmeding" yes remove substring 'med'
"proasdgrammiedg" no u have to remove 2 subtring 'asd' and 'ied'
which is not allowed
"pxrogramming" yes remove substring 'x'
"pxrogramminyg" no u have to remove 2 subtring 'x' and 'y'
which is not allowed
Please tell me an algorithm to solve it
{
// will create a regexp for fuzzy search
const factory = (str) => new RegExp(str.split('').join('(.*?)'), 'i')
const re = factory('test') // re = /t(.*?)e(.*?)s(.*?)t/i
const matches = re.exec('te-abc-st') ?? [] // an array of captured groups
const result = matches
.slice(1) // first element is a full match, we don't need it
.filter(group => group.length) // we're also not interested in empty matches
// now result contains a list of captured groups
// in this particular example a single '-abc-'
}
I'm not sure how efficient this code is, but only thing i can come up with is using regular expression.
const word = 'programming';
const test = ['progabcramming', 'programmmeding', 'proasdgrammiedg', 'pxrogramming', 'pxrogramminyg', 'programming'];
// create regular expression manually
// const regexp = /^(p).+(rogramming)|(pr).+(ogramming)|(pro).+(gramming)|(prog).+(ramming)|(progr).+(amming)|(progra).+(mming)|(program).+(ming)|(programm).+(ing)|(programmi).+(ng)|(programmin).+(g)$/;
// create regular expression programmatically
let text = '/^';
word.split('').forEach((character, i) => {
text += i ? `(${word.substring(0, i)}).+(${word.substring(i)})|` : '';
});
text = text.substring(text.length - 1, 1) + '$/';
const regexp = new RegExp(text);
// content output
let content = '';
test.forEach(element => {
content += `${element}: ${regexp.test(element)}\n`;
});
document.body.innerText = content;

(*SKIP)(*FAIL) workaround in JavaScript RegExp

I have a regex pattern that works fine in regex101.com: ~<a .*?">(*SKIP)(*FAIL)|\bword\b
I am trying to make it a Regexp so it can be used in the replace() function in JavaScript.
The line of JavaScript code is:
var regex = new RegExp("~<a.*?\">(*SKIP)(*FAIL)|\\b"+ word + "\\b", 'g');
Where word is the word I'm trying to match.
When I run it though, the console shows the following error:
Uncaught (in promise) SyntaxError: Invalid regular expression:
/~<a.*?">(*SKIP)(*FAIL)|word/: Nothing to repeat
Am I escaping characters wrong?
I tried backslash-escaping every special character I could find (?, *, < and so on) in my JavaScript code and it still spat out that error.
You can work around the missing (*SKIP)(*FAIL) support in JavaScript using capturing groups in the pattern and a bit of code logic.
Note the (*SKIP)(*FAIL) verb sequence is explained in my YT video called "Skipping matches in specific contexts (with SKIP & FAIL verbs)". You can also find a demo of JavaScript lookarounds for four different scenarions: extracting, replacing, removing and splitting.
Let's adjust the code for the current question. Let's assume word always consists of word characters (digits, letters or underscores).
Extracting: Capture the word into Group 1 and only extract Group 1 values:
const text = `foo foo foobar`;
const word = 'foo';
const regex = new RegExp(String.raw`<a .*?">|\b(${word})\b`, 'gi');
console.log(Array.from(text.matchAll(regex), x=>x[1]).filter(Boolean)); // => 1st word and `>foo<`
Removing: Capture the context you need to keep into Group 1 and replace with a backreference to this group:
const text = `foo foo foobar`;
const word = 'foo';
const regex = new RegExp(String.raw`(<a .*?">)|\b${word}\b`, 'gi');
console.log(text.replace(regex, '$1')); // => foobar
Replacing: Capture the context you need to keep into Group 1 and when it is used, replace with Group 1 value, else, replace with what you need in a callback function/arrow function used as the replacement argument:
const text = `foo foo foobar`;
const word = 'foo';
const regex = new RegExp(String.raw`(<a .*?">)|\b${word}\b`, 'gi');
console.log(text.replace(regex, (match, group1) => group1 || 'buz' ));
// => buz buz foobar
Splitting: This is the most intricate scenario and it requires a bit more coding:
const text = `foo foo foobar`;
const word = 'foo';
const regex = new RegExp(String.raw`(<a .*?">)|\b${word}\b`, 'gi');
let m, res = [], offset = 0;
while (m = regex.exec(text)) { // If there is a match and...
if (m[1] === undefined) { // if Group 1 is not matched
// put the substring to result array
res.push(text.substring(offset, m.index)) // Put the value to array
offset = m.index + m[0].length // Set the new chunk start position
}
}
if (offset < text.length) { // If there is any more text after offset
res.push(text.substr(offset)) // add it to the result array
}
console.log(res);
// => ["", " ", " foobar"]

.trim() for other characters?

Is there any function that can do .trim for specified characters or string?
Something like:
var x = '###hello world##';
console.log(x.trim('#')); // prints 'hello world'
var y = 'hellohellohelloworld';
console.log(y.trim('hello')); // prints ' world'
var z = '##hello#world##';
console log(z.trim('#')); // prints 'hello#world'
Even tho I can do without this, it would be way less efficient and not as clean
You can use a pattern with an alternation | to match either what you want to remove at the start or at the end of the string by repeating it 1 or more time in a non capture group.
The repetition looks like this (?:#)+ for a single # char, or like this (?:hello)+ for the word hello
If you want to make a function for it and want to pass any string, you have to escape the regex meta characters with a \
var x = '###hello world##';
var y = 'hellohellohelloworld';
var z = '##hello#world##';
var a = '*+hello*+'
const customTrim = (strSource, strToRemove) => {
let escaped = strToRemove.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
return strSource.replace(new RegExp(`^(?:${escaped})+|(?:${escaped})+$`, 'g'), "")
};
console.log(customTrim(x, "\\s"));
console.log(customTrim(y, "hello"));
console.log(customTrim(z, "#"));
console.log(customTrim(a, "*+"));
export function trim(str: string, char: string): string {
const leading = new RegExp(`^[${char}]+`);
const trailing = new RegExp(`[${char}]+$`);
return str.replace(leading, "").replace(trailing, "");
}

remove chars in String javascript Regex

I have a chain like this of get page
file.php?Valor1=one&Valor2=two&Valor3=three
I would like to be able to delete the get request parameter with only having the value of it. for example , remove two
Result
file.php?Valor1=one&Valor3=three
Try with
stringvalue.replace(new RegExp(value+"[(&||\s)]"),'');
Here's a regular expression that matches an ampersand (&), followed by a series of characters that are not equals signs ([^=]+), an equals sign (=), the literal value two and either the next ampersand or the end of line (&|$):
/&[^=]+=two(&|$)/
let input = 'file.php?&Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(/&[^=]+=two/, '');
console.log(output);
If you're getting the value to be removed from a variable:
let two = 'two';
let re = RegExp('&[^=]+=' + two + '(&|$)');
let input = 'file.php?&Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(re, '');
console.log(output);
In this case, you need to make sure that your variable value does not contain any characters that have special meaning in regular expressions. If that's the case, you need to properly escape them.
Update
To address the input string in the updated question (no ampersand before first parameter):
let one = 'one';
let re = RegExp('([?&])[^=]+=' + one + '(&?|$)');
let input = 'file.php?Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(re, '$1');
console.log(output);
You can use RegExp constructor, RegExp, template literal &[a-zA-Z]+\\d+=(?=${remove})${remove}) to match "&" followed by "a-z", "A-Z", followed by one or more digits followed by "", followed by matching value to pass to .replace()
var str = "file.php?&Valor1=one&Valor2=two&Valor3=three";
var re = function(not) {
return new RegExp(`&[a-zA-Z]+\\d+=(?=${not})${not}`)
}
var remove = "two";
var res = str.replace(re(remove), "");
console.log(res);
var remove = "one";
var res = str.replace(re(remove), "");
console.log(res);
var remove = "three";
var res = str.replace(re(remove), "");
console.log(res);
I think a much cleaner solution would be to use the URLSearchParams api
var paramsString = "Valor1=one&Valor2=two&Valor3=three"
var searchParams = new URLSearchParams(paramsString);
//Iterate the search parameters.
//Each element will be [key, value]
for (let p of searchParams) {
if (p[1] == "two") {
searchParams.delete(p[0]);
}
}
console.log(searchParams.toString()); //Valor1=one&Valor3=three

Use dynamic (variable) string as regex pattern in JavaScript

I want to add a (variable) tag to values with regex, the pattern works fine with PHP but I have troubles implementing it into JavaScript.
The pattern is (value is the variable):
/(?!(?:[^<]+>|[^>]+<\/a>))\b(value)\b/is
I escaped the backslashes:
var str = $("#div").html();
var regex = "/(?!(?:[^<]+>|[^>]+<\\/a>))\\b(" + value + ")\\b/is";
$("#div").html(str.replace(regex, "" + value + ""));
But this seem not to be right, I logged the pattern and its exactly what it should be.
Any ideas?
To create the regex from a string, you have to use JavaScript's RegExp object.
If you also want to match/replace more than one time, then you must add the g (global match) flag. Here's an example:
var stringToGoIntoTheRegex = "abc";
var regex = new RegExp("#" + stringToGoIntoTheRegex + "#", "g");
// at this point, the line above is the same as: var regex = /#abc#/g;
var input = "Hello this is #abc# some #abc# stuff.";
var output = input.replace(regex, "!!");
alert(output); // Hello this is !! some !! stuff.
JSFiddle demo here.
In the general case, escape the string before using as regex:
Not every string is a valid regex, though: there are some speciall characters, like ( or [. To work around this issue, simply escape the string before turning it into a regex. A utility function for that goes in the sample below:
function escapeRegExp(stringToGoIntoTheRegex) {
return stringToGoIntoTheRegex.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
var stringToGoIntoTheRegex = escapeRegExp("abc"); // this is the only change from above
var regex = new RegExp("#" + stringToGoIntoTheRegex + "#", "g");
// at this point, the line above is the same as: var regex = /#abc#/g;
var input = "Hello this is #abc# some #abc# stuff.";
var output = input.replace(regex, "!!");
alert(output); // Hello this is !! some !! stuff.
JSFiddle demo here.
Note: the regex in the question uses the s modifier, which didn't exist at the time of the question, but does exist -- a s (dotall) flag/modifier in JavaScript -- today.
If you are trying to use a variable value in the expression, you must use the RegExp "constructor".
var regex = "(?!(?:[^<]+>|[^>]+<\/a>))\b(" + value + ")\b";
new RegExp(regex, "is")
I found I had to double slash the \b to get it working. For example to remove "1x" words from a string using a variable, I needed to use:
str = "1x";
var regex = new RegExp("\\b"+str+"\\b","g"); // same as inv.replace(/\b1x\b/g, "")
inv=inv.replace(regex, "");
You don't need the " to define a regular expression so just:
var regex = /(?!(?:[^<]+>|[^>]+<\/a>))\b(value)\b/is; // this is valid syntax
If value is a variable and you want a dynamic regular expression then you can't use this notation; use the alternative notation.
String.replace also accepts strings as input, so you can do "fox".replace("fox", "bear");
Alternative:
var regex = new RegExp("/(?!(?:[^<]+>|[^>]+<\/a>))\b(value)\b/", "is");
var regex = new RegExp("/(?!(?:[^<]+>|[^>]+<\/a>))\b(" + value + ")\b/", "is");
var regex = new RegExp("/(?!(?:[^<]+>|[^>]+<\/a>))\b(.*?)\b/", "is");
Keep in mind that if value contains regular expressions characters like (, [ and ? you will need to escape them.
I found this thread useful - so I thought I would add the answer to my own problem.
I wanted to edit a database configuration file (datastax cassandra) from a node application in javascript and for one of the settings in the file I needed to match on a string and then replace the line following it.
This was my solution.
dse_cassandra_yaml='/etc/dse/cassandra/cassandra.yaml'
// a) find the searchString and grab all text on the following line to it
// b) replace all next line text with a newString supplied to function
// note - leaves searchString text untouched
function replaceStringNextLine(file, searchString, newString) {
fs.readFile(file, 'utf-8', function(err, data){
if (err) throw err;
// need to use double escape '\\' when putting regex in strings !
var re = "\\s+(\\-\\s(.*)?)(?:\\s|$)";
var myRegExp = new RegExp(searchString + re, "g");
var match = myRegExp.exec(data);
var replaceThis = match[1];
var writeString = data.replace(replaceThis, newString);
fs.writeFile(file, writeString, 'utf-8', function (err) {
if (err) throw err;
console.log(file + ' updated');
});
});
}
searchString = "data_file_directories:"
newString = "- /mnt/cassandra/data"
replaceStringNextLine(dse_cassandra_yaml, searchString, newString );
After running, it will change the existing data directory setting to the new one:
config file before:
data_file_directories:
- /var/lib/cassandra/data
config file after:
data_file_directories:
- /mnt/cassandra/data
Much easier way: use template literals.
var variable = 'foo'
var expression = `.*${variable}.*`
var re = new RegExp(expression, 'g')
re.test('fdjklsffoodjkslfd') // true
re.test('fdjklsfdjkslfd') // false
Using string variable(s) content as part of a more complex composed regex expression (es6|ts)
This example will replace all urls using my-domain.com to my-other-domain (both are variables).
You can do dynamic regexs by combining string values and other regex expressions within a raw string template. Using String.raw will prevent javascript from escaping any character within your string values.
// Strings with some data
const domainStr = 'my-domain.com'
const newDomain = 'my-other-domain.com'
// Make sure your string is regex friendly
// This will replace dots for '\'.
const regexUrl = /\./gm;
const substr = `\\\.`;
const domain = domainStr.replace(regexUrl, substr);
// domain is a regex friendly string: 'my-domain\.com'
console.log('Regex expresion for domain', domain)
// HERE!!! You can 'assemble a complex regex using string pieces.
const re = new RegExp( String.raw `([\'|\"]https:\/\/)(${domain})(\S+[\'|\"])`, 'gm');
// now I'll use the regex expression groups to replace the domain
const domainSubst = `$1${newDomain}$3`;
// const page contains all the html text
const result = page.replace(re, domainSubst);
note: Don't forget to use regex101.com to create, test and export REGEX code.
var string = "Hi welcome to stack overflow"
var toSearch = "stack"
//case insensitive search
var result = string.search(new RegExp(toSearch, "i")) > 0 ? 'Matched' : 'notMatched'
https://jsfiddle.net/9f0mb6Lz/
Hope this helps

Categories