javascript how match whole words but in certain length limit - javascript

for example i have this two strings:
string1:
"hi sir may name is Jone"
string2
"hi may name is Jone"
i have this this regex:
var regex = XRegExp('hi(?:(?!hi|Jone).)*?Jone', 'gs');
will match both of them but i want to modify the regex to match only in limited length of the whole string
i want to match the string two "hi may name is Jone" as had less words length how to do it..

If you want to get the string with the least amount of words that also matches your regex, you could split and use a whitespace as a separator and check the length of the returned array.
As an example with an array of strings, you could create var longestString = ""; which will at the end of the loop contain the shortest matched string.
In the loop, first check if there is a match and if longestString is an empty string. If that is the case then set the variable so you have a match to compare against future possible matches.
var strings = [
"test",
"hi sir may name is Jone",
"hi may name is Jone",
"hi Jone",
"hi may name is Jone test",
"hi i am Jone",
"may name is Jone test",
"hi may name is Jane test test 2"
];
var regex = /hi(?:(?!hi|Jone).)*?Jone/;
var longestString = "";
strings.forEach((str) => {
var match = XRegExp.match(str, regex);
if (match && longestString === "") {
longestString = str;
return;
}
if (match && str.split(" ").length < longestString.split(" ").length) {
longestString = str;
}
});
console.log(longestString);
<script src="https://unpkg.com/xregexp/xregexp-all.js"></script>

If you want to match a limited length of the whole string using only regex, I think you can do something like this:
var index = 15;
var testString1 = "hi may name is Jone";
var testString2 = "hi sir may name is Jone";
testString1.match("^.{1," + index + "}Jone"); // This will match
testString2.match("^.{1," + index + "}Jone"); // This string is longer and will not match
Explanation of the regex ^.{1, n}Jone.
^ : should match the start of the string.
.{1, n}Jone : matches everything between 1 to n until the pattern is fully matched.
In this case we define the n as index so this "limit" can be dynamic.
Hope this helps!

Related

How can I split commas and periods from words inside of string using split?

I am trying to change specific word in a string with something else. For example, I want to change 'John' in let name = 'Hi, my name is John.'; to 'Jack'.
I know how to split a string by words or characters. I also know how to remove commas, periods, and other symbols in a string. However, if I split the given string with a separator (" "), I will have 'John.' which I do not want. (I know I can switch 'John.' with 'Jack.' but assume that I have an key and value pairs in an object and I am using the values which are names {Father: Jack, Mother: Susan, ...}
I don't know how to separate a string word by word including commas and periods.
For example, if I was given an input which is a string:
'Hi, my name is John.'
I want to split the input as below:
['Hi', ',', 'my', 'name', 'is', 'John', '.']
Does anyone know how to do it?
Below is the challenge I am working on.
Create a function censor that accepts no arguments. censor will return a function that will accept either two strings, or one string. When two strings are given, the returned function will hold onto the two strings as a pair, for future use. When one string is given, the returned function will return the same string, except all instances of a first string (of a saved pair) will be replaced with the second string (of a saved pair).
//Your code here
const changeScene = censor();
changeScene('dogs', 'cats');
changeScene('quick', 'slow');
console.log(changeScene('The quick, brown fox jumps over the lazy dogs.')); // should log: 'The slow, brown fox jumps over the lazy cats.'
I think your real question is "How do I replace a substring with another string?"
Checkout the replace method:
let inputString = "Hi, my name is John.";
let switch1 = ["John", "Jack"];
let switched = inputString.replace(switch1[0], switch1[1]);
console.log(switched); // Hi, my name is Jack.
UPDATE: If you want to get ALL occurrences (g), be case insensitive (i), and use boundaries so that it isn't a word within another word (\\b), you can use RegExp:
let inputString = "I'm John, or johnny, but I prefer john.";
let switch1 = ["John", "Jack"];
let re = new RegExp(`\\b${switch1[0]}\\b`, 'gi');
console.log(inputString.replace(re, switch1[1])); // I'm Jack, or johnny, but I prefer Jack.
You can Try This ...
var string = 'Hi, my name is John.';
//var arr = string.split(/,|\.| /);
var arr = string.split(/([,.\s])/);
console.log(arr);
Using 'Hi, my name is John.'.split(/[,. ]/); will do the job. It will split commas and periods and spaces.
Edit: For those who want to keep the comma and period, here is my wildly inefficient method.
var str = 'Hi, my name is John.'
str = str.replace('.', 'period');
str = str.replace(',', 'comma');
str = str.split(/[,. ]/);
for (var i = 0; i < str.length; i++) {
if (str[i].indexOf('period') > -1) {
str[i] = str[i].replace('period', '');
str.splice(i+1, 0, ".");
} else if (str[i].indexOf('comma') > -1) {
str[i] = str[i].replace('comma', '');
str.splice(i+1, 0, ",");
}
}
console.log(str);

How to match a string inside another string while ignoring whitespace

I have a string to search, and I need to match and return another string at the beginning of the search string. The string being searched may have whitespace in it, which needs to be ignored for the purpose of searching, but still returned accurately. The string to be matched will never have whitespace in it.
stringA = "ThisIsAString";
Should give the following results when compared to stringB:
stringB = "This Is A String"; //"This Is A String"
stringB = "ThisIsAlsoAString"; //undefined
stringB = "ThisIs A String With Extra Words At The End"; //"ThisIs A String"
stringB = "Hey, ThisIsAString"; //undefined
What's an efficient way to do this?
You can use \s* to match zero or more spaces. With the code below we put one of those matchers between each character.
const stringA = "ThisIsAString";
const tests = [
"This Is A String",
"ThisIsAlsoAString",
"ThisIs A String With Extra Words At The End",
"Hey, ThisIsAString",
];
const optionalSpaces = '\\s*';
const results = tests.map(test =>
test.match(
new RegExp(stringA.split('').join(optionalSpaces))
)
);
console.log(results);
An easy way to do this would be to remove all white space from the two things you are comparing.
var search = "Hello There";
var text = "HelloThere I'm Greg";
var found = text.replace(/ +?/g, '').indexOf(search.replace(/ +?/g, '')) !== -1;

Why is this regex matching also words within a non-capturing group?

I have this string (notice the multi-line syntax):
var str = ` Number One: Get this
Number Two: And this`;
And I want a regex that returns (with match):
[str, 'Get this', 'And this']
So I tried str.match(/Number (?:One|Two): (.*)/g);, but that's returning:
["Number One: Get this", "Number Two: And this"]
There can be any whitespace/line-breaks before any "Number" word.
Why doesn't it return only what is inside of the capturing group? Am I misundersating something? And how can I achieve the desired result?
Per the MDN documentation for String.match:
If the regular expression includes the g flag, the method returns an Array containing all matched substrings rather than match objects. Captured groups are not returned. If there were no matches, the method returns null.
(emphasis mine).
So, what you want is not possible.
The same page adds:
if you want to obtain capture groups and the global flag is set, you need to use RegExp.exec() instead.
so if you're willing to give on using match, you can write your own function that repeatedly applies the regex, gets the captured substrings, and builds an array.
Or, for your specific case, you could write something like this:
var these = str.split(/(?:^|\n)\s*Number (?:One|Two): /);
these[0] = str;
Replace and store the result in a new string, like this:
var str = ` Number One: Get this
Number Two: And this`;
var output = str.replace(/Number (?:One|Two): (.*)/g, "$1");
console.log(output);
which outputs:
Get this
And this
If you want the match array like you requested, you can try this:
var getMatch = function(string, split, regex) {
var match = string.replace(regex, "$1" + split);
match = match.split(split);
match = match.reverse();
match.push(string);
match = match.reverse();
match.pop();
return match;
}
var str = ` Number One: Get this
Number Two: And this`;
var regex = /Number (?:One|Two): (.*)/g;
var match = getMatch(str, "#!SPLIT!#", regex);
console.log(match);
which displays the array as desired:
[ ' Number One: Get this\n Number Two: And this',
' Get this',
'\n And this' ]
Where split (here #!SPLIT!#) should be a unique string to split the matches. Note that this only works for single groups. For multi groups add a variable indicating the number of groups and add a for loop constructing "$1 $2 $3 $4 ..." + split.
Try
var str = " Number One: Get this\
Number Two: And this";
// `/\w+\s+\w+(?=\s|$)/g` match one or more alphanumeric characters ,
// followed by one or more space characters ,
// followed by one or more alphanumeric characters ,
// if following space or end of input , set `g` flag
// return `res` array `["Get this", "And this"]`
var res = str.match(/\w+\s+\w+(?=\s|$)/g);
document.write(JSON.stringify(res));

How to "place-hold" regex matches in array using javascript

If I have a multiple match regex like:
var matches = string.match(/\s*(match1)?\s*(match2)?(match3)?\s*/i);
and if my string that I am testing is like this:
var string = "match1 match3";
is there a way to output this array values:
matches[1] = "match1";
matches[2] = "";
matches[3] = "match3";
Notice: what I would like is for the regex to match the entire thing but "place-hold" in the array the matches it does not find.
Hope this makes sense. Thanks for the help!
There already is a "placeholder". Unmatched groups pop an array index matching the group number with an undefined value. e.g.
var someString = "match2";
var matches = someString.match(/\s*(match1)?\s*(match2)?(match3)?\s*/i);
matches now has
["match2", undefined, "match2", undefined]
Element 0 is the complete regex match and elements 1-3 are the individual groups
So you can do for example...
// check if group1
if (typeof matches[1] != 'undefined')
When you want to compare the string to the regexes, just do an Array join.Something like,
matches[1] = "match1";
matches[2] = "";
matches[3] = "match3";
var mystring = mathches.join("");
The joining character could be anything. You could also do,
var mystring = mathches.join(" ");
EDIT:
Not sure from the problem description, but i think you want the regex to output an array.Something like
text = "First line\nSecond line";
var regex = /(\S+) line\n?/y;
would give,
var match = regex.exec(text);
print(match[1]); // prints "First"
print(regex.lastIndex); // prints 11
More about it here

How to Split string with multiple rules in javascript

I have this string for example:
str = "my name is john#doe oh.yeh";
the end result I am seeking is this Array:
strArr = ['my','name','is','john','&#doe','oh','&yeh'];
which means 2 rules apply:
split after each space " " (I know how)
if there are special characters ("." or "#") then also split but add the characther "&" before the word with the special character.
I know I can strArr = str.split(" ") for the first rule. but how do I do the other trick?
thanks,
Alon
Assuming the result should be '&doe' and not '&#doe', a simple solution would be to just replace all . and # with & split by spaces:
strArr = str.replace(/[.#]/g, ' &').split(/\s+/)
/\s+/ matches consecutive white spaces instead of just one.
If the result should be '&#doe' and '&.yeah' use the same regex and add a capture:
strArr = str.replace(/([.#])/g, ' &$1').split(/\s+/)
You have to use a Regular expression, to match all special characters at once. By "special", I assume that you mean "no letters".
var pattern = /([^ a-z]?)[a-z]+/gi; // Pattern
var str = "my name is john#doe oh.yeh"; // Input string
var strArr = [], match; // output array, temporary var
while ((match = pattern.exec(str)) !== null) { // <-- For each match
strArr.push( (match[1]?'&':'') + match[0]); // <-- Add to array
}
// strArr is now:
// strArr = ['my', 'name', 'is', 'john', '&#doe', 'oh', '&.yeh']
It does not match consecutive special characters. The pattern has to be modified for that. Eg, if you want to include all consecutive characters, use ([^ a-z]+?).
Also, it does nothing include a last special character. If you want to include this one as well, use [a-z]* and remove !== null.
use split() method. That's what you need:
http://www.w3schools.com/jsref/jsref_split.asp
Ok. i saw, you found it, i think:
1) first use split to the whitespaces
2) iterate through your array, split again in array members when you find # or .
3) iterate through your array again and str.replace("#", "&#") and str.replace(".","&.") when you find
I would think a combination of split() and replace() is what you are looking for:
str = "my name is john#doe oh.yeh";
strArr = str.replace('\W',' &');
strArr = strArr.split(' ');
That should be close to what you asked for.
This works:
array = string.replace(/#|\./g, ' &$&').split(' ');
Take a look at demo here: http://jsfiddle.net/M6fQ7/1/

Categories

Resources