Function to match string to one of many regex? - javascript

I currently have the following function, which works:
String.prototype.matchAny = function(patterns) {
var that = this;
var matched = false;
// Iterate patterns and return key of first match
$.each(patterns, function(i, v) {
if (that.match(v)) {
matched = i;
return false;
}
});
return matched;
};
It will return the index in patterns of the first matched regular expression for the string. For example:
"blah".matchAny([/a/, /z/]); // 0
"blah".matchAny({z: /z/, a: /a/]); // "a"
However, this solution feels clunky to me. I've had some success using Array.some(), and while it's a lot more elegant, I can't find a way to get the result I want (return the key from patterns that matched).
Is there something I'm missing? More specifically, is there a built-in function (JavaScript/jQuery) that can produce the same results?

Related

Writing indexOf function in JavaScript

I am new to JavaScript. I have created a indexof function in but it is not giving the correct output:
Question is:
/*
Implement a function called indexOf that accepts two parameters: a string and a character, and returns the first index of character in the string.
*/
This is my code:
function indexOf(string, character) {
let result = string;
let i = 0;
let output = 1;
while (i < result.length) {
if (result[i] === character) {
output = output + indexOf[i];
}
}
return output;
}
I want to know what i am doing wrong. Please Help.
You are making things a little harder than you need to. If you want to do this without calling the built-in indexOf(), which I assume is the point of the exercise, you just need to return from the function as soon as your condition matches. The instructions say "return the first index" — that's the i in your loop.
If you make it through the loop without finding something it's traditional to return -1:
function indexOf(string, character) {
let i=0;
while(i < string.length){
if(string[i] == character){ // yes? just return the index i
return i
}
i++ // no? increase i and move on to next loop iteration
}
return -1; // made it through the loop and without returning. This means no match was found.
}
console.log(indexOf("Mark Was Here", "M"))
console.log(indexOf("Mark Was Here", "W"))
console.log(indexOf("Mark Was Here", "X"))
Assuming from your question that the exercise is to only match the first occurrence of a character and not a substring (multiple characters in a row), then the most direct way to do it is the following:
const indexOf = (word, character) => {
for (let i = 0; i < word.length; i++) {
if (word[i] === character) {
return i;
}
}
return -1;
}
If you also need to match substrings, leave a comment on this answer if you can't figure it out and I'll help you along.
indexOf() is a built in method for strings that tells you the index of a particular character in a word. Note that this will always return the index of the FIRST matching character.-
You can write something like:
function indexOf(string, character){
return string.indexOf(character)
}
So if I were to use my function and pass in the two required arguments:
indexOf("woof", "o") //this would return 1

How to match a "something":"thestring" pattern?

Note: I changed the title of the question, as well as all reference to JSON so that the question better reflects my problem. I got several times the advice of "better iterate the object than work on a serialized version" but I believe (and am certainly mistaken and wrong) that searching for a well-defined pattern in a string is easier than go for iterative or recursive code to iterate an object
I need to extract the pattern "something":"thestring" from a string.
The source string will have many other combinations such as "something":[{"thestring":{"key":18,"anotherkey":"astring"}}], from which only the pair "anotherkey":"astring" is sought for.
I am specifically interested in getting the content of the value, that is thestring in the first example (and astring in the second one).
I tried to match ".*?","(.*?)" but I get more than just the pair, matching the comma after the quote (and it goes downhill form there).
An example of a test string and my failed test is on Regex101
Here is how I would write this:
function extractStrings(obj) {
var stringSet = [];
function extractStringsHelper(obj) {
if (typeof obj === 'string' && stringSet.indexOf(obj) === -1) {
stringSet.push(obj);
} else if (typeof obj === 'array') {
for (var i=0; i<obj.length; i++) {
extractStringsHelper(obj);
}
} else if (typeof obj === 'object' && obj !== null) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
extractStringsHelper(obj[key]);
}
}
}
}
extractStringsHelper(obj);
return stringSet;
}
> extractStrings({'a': "strA", 'b': ["strB1", 1, "strB2", {'n': "strC"}]})
> (4) ["strA", "strB1", "strB2", "strC"]
You can also go the regex route and look for:
"[^"]+":"([^"]+)"
Here is your example with the modified regex: https://regex101.com/r/uxS9k0/2
But this path is dark and full of terrors. For example, it breaks if the string contains an escaped double quote. Once you start accounting for all the possible cases, you are basically rewriting a JSON tokenizer.
Try this regex :
If you really want to work on a string, this regex will do what you want, as long as what you look for is always between quotes and preceded by a key between quotes :
"\w+":"(\w+)"
Demo here
The value will be captured in group 1
Here is how to get your value :
var regex = /"\w+":"(\w+)"/g;
var json = "\"something\":\"thestring\"\n\"something\":[{\n\t\"thestring\":{\n\t\t\"key\":18,\n\t\t\"anotherkey\":\"astring\"\n\t}\n}]";
console.log(json);
var match = regex.exec(json);
for (i = 1; match != null; i++) { // You need to loop until you match every value
// Full match is in match[0]
// Your value is in match[1]
console.log("Val"+i+": "+match[1])
match = regex.exec(json);
}
If you are working with valid json you shouldn't need to use regex, and can deserialize it with the following:
var data = JSON.parse(json_string);

How to check if a string only contains chars from an array?

I try to check if a word (wordToCheck) only consists of letters from an array (letters) and also contains every letter in the array only as often (or rather not more times than they are in the array) as it actually is inside of the array.
Here are examples of what the desired function should return:
checkIfWordContainsLetters("google", ["a","o","o","g","g","l","e","x"]) === true
checkIfWordContainsLetters("google", ["a","o","g","g","l","e","x"]) === false
How can I make this code work?
function checkIfWordContainsLetters(wordToCheck, letters) {
var lettersToString = letters.toString();
var lettersTrimmed = lettersToString.replace(/,/gi, "?");
var regEx = new RegExp(lettersTrimmed, "gi");
if (wordToCheck.match(regEx)!== null) {
return true;
}
else return false;
}
You could use this ES6 function:
function checkIfWordContainsLetters(wordToCheck, letters){
return !letters.reduce((a, b) => a.replace(b,''), wordToCheck.toLowerCase()).length;
}
console.log(checkIfWordContainsLetters("google", ["a","o","o","g","g","l","e","x"]));
console.log(checkIfWordContainsLetters("google", ["a","o","g","g","l","e","x"]));
The idea is to go through each letter in the letters array, and remove one (not more!) occurrence of it in the given wordToCheck argument (well, not exactly in it, but taking a copy that lacks that one character). If after making these removals there are still characters left over, the return value is false -- true otherwise.
Of course, if you use Internet Explorer, you won't have the necessary ES6 support. This is the ES5-compatible code:
function checkIfWordContainsLetters(wordToCheck, letters){
return !letters.reduce(function (a, b) {
return a.replace(b, '');
}, wordToCheck.toLowerCase()).length;
}
console.log(checkIfWordContainsLetters("google", ["a","o","o","g","g","l","e","x"]));
console.log(checkIfWordContainsLetters("google", ["a","o","g","g","l","e","x"]));
As long as it is not the best solution for long strings for which using some clever regex is definitely better, it works for short ones without whitespaces.
function checkIfWordContainsLetters(word, letters){
word = word.toLowerCase().split('');
for(var i = 0; i < letters.length; i++) {
var index = word.indexOf( letters[i].toLowerCase() );
if( index !== -1 ) {
// if word contains that letter, remove it
word.splice( index , 1 );
// if words length is 0, return true
if( !word.length ) return true;
}
}
return false;
}
checkIfWordContainsLetters("google", ["a","o","o","g","g","l","e","x"]); // returns true
checkIfWordContainsLetters("google", ["a","o","g","g","l","e","x"]); // returns false

How to remove spaces and special characters from string?

I have a function that returns true if a character is a form of punctuation and I'm trying to write another function that accepts a string and removes the spaces and punctuation marks while calling the first function. I got most of it I think. But now I'm stuck. Any help is appreciated.
var isPunct = function(ch) {
if (ch = ch.match(/[,.!?;:'-]/g))
return true
else
return false
}
//B
var compress = function(s) {
var result = "";
//loop to traverse s
for (var i = 0; i < s.length; i++) {
if (!(isPunct(ch));
//(isPunct(s.charAt(i) || s.charAt(i) == " "));
//do nothing
else
result = result + !compress(i)
}
return result
}
Some issues:
The inner condition should in fact be the opposite: you want to do nothing when it is a punctuation character, i.e. you don't want to add it to the result. Only in the other case you want to do that.
The call !compress(i) is wrong: first of all that function expects a string, not an index, and it returns a string, not a boolean (so to perform ! on it). It seems like you want to call your function recursively, and although that is an option, you are also iterating over the string. You should do one of the two: recursion or iteration.
You reference a variable ch in the compress function which you have not defined there.
So, if you want to write compress the iteration way, change your code as follows:
var compress = function(s) {
var result = "", ch; // define ch.
//loop to traverse s
for (var i = 0; i < s.length; i++) {
ch = s[i]; // initialise ch.
if (!isPunct(ch)) result = result + ch; // only add when not punctuation
}
return result;
}
If on the other hand you want to keep your recursive call to compress, then you should do away with your for loop:
var compress = function(s) {
var result = "", ch, rest;
if (s.length == 0) return '';
result = compress(s.substr(1)); // recursive call
ch = s[0];
if (!isPunct(ch)) result = ch + result;
return result;
}
The function isPunct also has a strange thing happening: it assigns a boolean value to ch in the if expression. This does not make your function malfunction, but that assignment serves no purpose: the match method already returns the boolean you need for your if condition.
It is also not really nice-looking to first evaluate a boolean expression in an if to then return that same value in the form of false and true. This you can do by just returning the evaluated expression itself:
var isPunct = function(ch) {
return ch.match(/[,.!?;:'-]/g);
}
On a final note, you don't really need the isPunct function if you only use it in compress. The whole logic can be performed in one function only, like this:
let compress = s => s.replace(/[,.!?;:'-]/g,'');
// Demo:
console.log(compress('a,b,c')); // abc
If you prefer to keep isPunct and don't want to repeat the regular expression elsewhere, then you can do the replace like this:
let isPunct = ch => ch.match(/[,.!?;:'-]/g);
let compress = s => Array.from(s).filter(ch => !isPunct(ch)).join('');
// Demo:
console.log(compress('a,b,c')); // abc
Note how the use of ES6 arrow functions and ES5 Array methods makes the code quite lean.

Getting all var from a javastring function by Regular Expression

Hi I am new for Regex and trying to get below,
there is a string below in javascript,
"function(){var a; var a,b,c;}"
and I am trying to find [a,b,c] from it.
Please suggest me to get all variable declared in string, what will be regex.
A very very manipulative solution, but will serve your purpose
function uniq(value,index,self){
return self.indexOf(value) === index;
}
var str = "function(){var a; var a,b,c;}";
var ptrn = /var [^;]+/g;
var match;
var matches = []
while ( ( match = ptrn.exec(str) ) != null )
{
matches.push(match.join().split(" ")[1]);
}
console.log(matches.join(",").split(",").filter(uniq));
but if you understand this code you wont have to ever search for:
how to get unique values from js array
how matching a pattern with exec only returns the first match and we have to loop to get the rest of the values
finally adding a filter with a function.

Categories