how can I fix this regular expression function? - javascript

This is the first part of my code in a function:
var pattern = new RegExp(myTypedString,"gi");
The goal is to populate results as I type in a text field. Everytime an input event is triggered I loop through an array of strings and check if my typed string exists in my array of strings using this code:
return pattern.test(myArrayString);
but luckily I've realised that one of the results was wrong and it was only happening to this particular case: when I type "t" or "T" I don't have a match in "Trafalgar Square" (a string from myArrayString), so I did a few debugging in the console and when I check the variable pattern doing console.log(pattern) it outputs this string: /t/gi, which i think it's where my problem relies... (later on this)
when I tried to replicate the problem typing:
var pattern = new RegExp('t',"gi")
and:
pattern.test('Trafalgar Square')
which gives me true at a first try, BUT... if I type this again:
pattern.test('Trafalgar Square')
the result will be false and if I continue, true, false, true, false,...
One of the first things that came into my mind is that the /t in the regex /t/gi might be a rule but I couldn't find anything about it.
I would like to know an explanation for this unexpected result but I'm also concerned that my function is not flawless, so I ask you how can I improve this function? thanks

It alternates between true and false because it matches the first time (true), then tries a second match, which fails because there’s only one T in Trafalgar Square. When you call it again, it loop back, thus the true, false, true, etc.
To fix that, update its cursor before matching:
var p = new Regexp('t', 'gi') // same as `p = /t/gi`
// ...
p.lastIndex = 0;
p.test("Trafalgar Square"); // true
// try again:
p.lastIndex = 0;
p.test("Trafalgar Square"); // true -> it works
Here is a relevant jsfiddle with a couple examples.

I do not know why it alternates between true and false (i can reproduce it, too). The /t/ should not be anything special in the regex. It is not a special character like { or \ or [ and should just be a literal character t.
But you could use another function to achieve more or less the same:
'Trafalgar Square'.match(pattern)
=> Array [ "T" ]
'lalala'.match(pattern)
=> null
match takes slightly more resources than test would, but this is usually not a problem. The result will be an Array for matches or null when nothing matches, so you can just return that and the rest of your code will probably work just fine. Array... will be a truthy value and null will be a falsy value.

Related

JavaScript string.includes() method at specific index, without modifying original string?

I am wondering if there's a way to use the str.includes() function in JavaScript, but check at a certain index of the string, without changing the original string. For example:
var str = "this is a test";
str.includes("test"); //returns true
str.includes("test", 0) //returns false, as "test" is not at position 0
str.includes("test", 10) //returns true, as "test" is at position 10 in the string
I've been trying to find a way to do this, but haven't been able to figure it out. Could somebody please help me?
String.prototype.includes() has something close to this functionality, as argument 2 is taken as the start position for searching.
If you want to search at, not after, a specific index, you can write a function that takes the string, creates a slice of it, and checks if that slice matches
function substring_at(string, substring, position) {
let slice = string.slice(position, position + substring.length)
// Triple equals removes type coercion support, and is slightly faster
return slice === substring
}
I've tested it with your examples and all seems well.

Create function REGEX for optimization

I've been asked to optimize the speed of my query. I currently have this regex in my query, which is checking for a pattern and returning substring within that pattern. To clarify I have a table with multiple columns that I have to look through to check for this value: [v= and return the numbers within that list.
This is looking through several 'name..' columns that look something like this: xyzzy [v=123] but I only want to return 123, the below works:
COALESCE(REGEXP_SUBSTR(NAME, '[[]v=([0-9]+)', 1, 1, 'ie'),
REGEXP_SUBSTR(NAME_5, '[[]v=([0-9]+)', 1, 1, 'ie'),
REGEXP_SUBSTR(NAME_4, '[[]v=([0-9]+)', 1, 1, 'ie')) as display_vertical_code
but to optimize this, I thought of maybe creating a function unfortunately I don't know javascript :/ and I don't know if the formatting is correct I'm having some difficulties creating it, this is what I've tried, can someone tell me if I'm missing something?
CREATE OR REPLACE FUNCTION dfp.regex(NAME VARCHAR)
RETURNS OBJECT
LANGUAGE javascript
STRICT AS '
return new RegExp(NAME,"[[]v=([0-9]+)",1 ,1,"ie")
';
When I try to use the above function in my below query:
COALESCE(
GET(DFP.REGEX(NAME)),
GET(DFP.REGEX(NAME_5)),
GET(DFP.REGEX(NAME_4)),
GET(DFP.REGEX(NAME_3)),
GET(DFP.REGEX(NAME_2)),
GET(DFP.REGEX(NAME_1)),
GET(DFP.REGEX(NAME_0))
) as display_vertical_code
I see this error:
error line 3 at position 8 not enough arguments for function
[GET(REGEX(Tablename.NAME))], expected 2, got 1
This should do it.
CREATE OR REPLACE FUNCTION regex(NAME VARCHAR)
RETURNS string
LANGUAGE javascript
STRICT IMMUTABLE AS
$$
const regex = /[[]\s{0,5}v\s{0,5}=\s{0,5}([0-9]+)/i;
let s = NAME.match(regex);
if (s != null) {
return s[0].split('=')[1].trim();
} else {
return null;
}
$$;
select regex('xyzzy [v=123]');
-- Alternate permutation
select regex('xyzzy [ v = 123]');
You want to return a string, not an object. Adding the IMMUTABLE option tells Snowflake that the same input results in the same output every time. It can sometimes help with performance.
Edit... This one's a bit more fault tolerant and allows whitespace (if that could be a problem). If you want to get rid of allowing whitespace, delete the \s{0,5} expressions.

return true if only there is exact include

Using includes method we get true for all of these logs:
console.log("https://example.com/test/media/instructions/listen_again_long/1.mp3".includes('listen_again_long')); // true
console.log("https://example.com/test/media/instructions/listen_again_long/2.mp3".includes('listen_again')); // true
console.log("https://example.com/test/media/instructions/listen_again_long/3.mp3".includes('listen')); // true
But we know only the first log should return true because we have exactly listen_again_long inside the longer string.
if we consider this part fixed: https://example.com/test/media/instructions/
How we can only return true for the first one and false for the rest of the logs?
You are actually looking for a certain string enclosed in /, so one option would be to simply include both / in the argument you are passing to String.prototype.includes():
console.log("https://example.com/test/media/instructions/listen_again_long/1.mp3".includes('/listen_again_long/'));
console.log("https://example.com/test/media/instructions/listen_again_long/2.mp3".includes('/listen_again/'));
console.log("https://example.com/test/media/instructions/listen_again_long/3.mp3".includes('/listen/'));
You could also do the same thing using RegExps and RegExp.prototype.test():
console.log(/\/listen_again_long\//.test("https://example.com/test/media/instructions/listen_again_long/1.mp3"));
console.log(/\/listen_again\//.test("https://example.com/test/media/instructions/listen_again_long/2.mp3"));
console.log(/\/listen\//.test("https://example.com/test/media/instructions/listen_again_long/3.mp3"));
In both cases you could replace /listen_again_long/ with the whole thing if you want to make sure the match doesn't happen in a different place:
"...".includes("https://example.com/test/media/instructions/listen_again_long/");
Or, with RegExp:
/https:\/\/example.com\/test\/media\/instructions\/listen_again_long\//.test("...");
You'll have to extract the substring you want to compare against your parameter and then do a straight === comparison.
var url = <your passed in mp3 file>;
var s = "https://example.com/test/media/instructions/"
var substring = url.substring(url.indexOf(s) + url.length);
substring = substring.substring(0, url.indexOf("/");
substring === "listen_again_long"

How to access the first two digits of a number

I want to access the first two digits of a number, and i have tried using substring, substr and slice but none of them work. It's throwing an error saying substring is not defined.
render() {
let trial123 = this.props.buildInfo["abc.version"];
var str = trial123.toString();
var strFirstThree = str.substring(0,3);
console.log(strFirstThree);
}
I have tried the above code
output of(above code)
trial123=19.0.0.1
I need only 19.0
How can i achieve this?
I would split it by dot and then take the first two elements:
const trial = "19.0.0.1"
console.log(trial.split(".").slice(0, 2).join("."))
// 19.0
You could just split and then join:
const [ first, second ] = trial123.split('.');
const result = [ first, second ].join('.');
I have added a code snippet of the work: (explanation comes after it, line by line).
function getFakePropValue(){
return Math.round(Math.random()) == 0 ? "19.0.0.1" : null;
}
let trial123 = getFakePropValue() || "";
//var str = trial123.toString();
// is the toString() really necessary? aren't you passing it along as a String already?
var strFirstThree = trial123.split('.');
//var strFirstThree = str.substring(0,3);
//I wouldn't use substring , what if the address 191.0.0.1 ?
if(strFirstThree.length >= 2)
console.log(strFirstThree.splice(0,2).join("."));
else
console.error("prop was empty");
Because you are using React, the props value was faked with the function getFakePropValue. The code inside is irrelevant, what I am doing is returning a String randomly, in case you have allowed in your React Component for the prop to be empty. This is to show how you an create minimal robust code to avoid having exceptions.
Moving on, the following is a safety net to make sure the variable trial123 always has a string value, even if it's "".
let trial123 = getFakePropValue() || "";
That means that if the function returns something like null , the boolean expression will execute the second apart, and return an empty string "" and that will be the value for trial123.
Moving on, the line where you convert to toString I have removed, I assume you are already getting the value in string format. Next.
var strFirstThree = trial123.split('.');
That creates an array where each position holds a part of the IP addrss. So 19.0.0.1 would become [19,0,0,1] that's thanks to the split by the delimiter . . Next.
if(strFirstThree.length >= 2)
console.log(strFirstThree.splice(0,2).join("."));
else
console.error("prop was empty");
This last piece of code uses the conditional if to make sure that my array has values before I try to splice it and join. The conditional is not to avoid an exception, since splice and join on empty arrays just returns an empty string. It's rather for you to be able to raise an error or something if needed. So if the array has values, I keep the first two positions with splice(0,2) and then join that array with a '.'. I recommend it more than the substr method you were going for because what if you get a number that's 191.0.0.1 then the substr would return the wrong string back, but with splice and join that would never happen.
Things to improve
I would strongly suggest using more human comprehensible variables (reflect their use in the code)
The right path for prop value checking is through Prop.Types, super easy to use, very helpful.
Happy coding!

JavaScript: Guessing password

Another JavaScript question I found on the internet, but I couldn't figure out how it works. The question basically asks what is the password. The password doesn't depend on external resources and it doesn't change over time (do not depends on current date or time). Also, question says that there is exactly one correct password. I am JavaScript begginer, so I apologize if this is a simple standard interview question. This is the function:
const checkPassword = a => {
if(a !== (a += '')) return false;
if(a !== (a = a.replace(/[^a-z]/g, ''))) return false;
a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]);
a = [...a].reverse().join([] + []);
try{
Function('\'' + a + '\';++1..a')();
return false;
}catch(a){
return true;
}
};
alert(checkPassword(prompt('Enter password:')) ? 'Correct password.' : 'Wrong. Try again.');
At first, this didn't look hard too me, because everything is open, so I can simply follow code line by line and figure out how does it work. Ok, I understand that in the first line of check function they check if password is a string (why? Can it be something else?). Then, if I understood that regex well, they check if script consists only of small alphabet letters (or am I wrong?). So, for now I know I know it must consists only of letters. After that they perform some weird regex I cannot fully understand. It seems to me that this regex will match whole string, so why they are joining it?
Then they reverse string and join by an empty array (is it same as normally reversing string or what?). After that in try block I cannot understand what is happening? What does Function constructor actually do here? What is the meaning of ++1..a? Im just wondering how to approach questions like this one?
I'll jump straight to the key line:
Function('\'' + a + '\';++1..a')();
It creates and then immediately executes a new function with a function body set from that weird-looking string. If the variable a is, say, 'abcde' then the new function's body will be:
'\'' + 'abcde' + '\';++1..a'
which is like having this function:
function() {
'abcde';++1..a
}
Or with some whitespace:
function() {
'abcde';
++1..a
}
Note that the string on the first line is dynamically set based on what is in the a variable, but the ++1..a part is hardcoded.
Now, noting that the function is inside a try/catch() block, if the new function runs without error then checkPassword() will return false, but if the new function crashes checkPassword() returns true. In other words, it is expected that the behaviour of that dynamic function will change to crash or not depending on what is in the string from the a variable.
So what string, by itself on the first line of a function, can possibly change the behaviour of the function? There is only one possibility, and that is (hover to reveal spoiler):
'use strict' ...which would have to be entered as the password 'tcirtsesu' because of the first few lines of the function doing the .match() and .reverse().
With that in mind it doesn't even really matter what the ++1..a part does, but it is basically taking the .a property of 1, which is undefined, and trying to increment it, which...
is an error in strict mode but not in non-strict mode.
For completeness, a very brief explanation of these lines:
a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]);
a = [...a].reverse().join([] + []);
The .match() function returns an array. /^.{6}|.+/g matches the first six characters, OR any number of characters, which means that "abcdefghijkl".match(/^.{6}|.+/g) returns ["abcdef", "ghijkl"]. Then ({} + {})[7] is basically just a space character because {} + {} is the string "[object Object][object Object]". So that line basically inserts a space after the sixth character.
The .reverse() line then reverses the result of that.

Categories

Resources