Create function REGEX for optimization - javascript

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.

Related

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.

Javascript Unnecessarily Compact Array Operations

So, for my own knowledge, and because I love looking at things from a different perspective...
I have the following bite of Javascript code, which for this problem's intents and purposes will only ever receive strings formatted like this: "wordone wordtwo":
function inName(inputName) {
return inputName.split(" ")[1].toUpperCase();
}
However, this only returns half of what I want ("WORDTWO"). I desire to return the original string with a single change: the space-separated second word returned through the toUpperCase(); and then re-concatenated to the untouched first word.
I also want to unnecessarily run all of the operations on the return line. My brain says this is possible, given how as the compiler reads the line from left to right and makes adjustments to the available member functions based on what has resolved. Also everything in Javascript is an object, correct?
Help me out for my own curiosity's sake, or bash me over the head with my own misconceptions.
Here is a solved version of the above question using 'normal' statements:
function inName(inputName) {
var nameArray=inputName.split(" ");
nameArray[1]=nameArray[1].toUpperCase();
return nameArray.join(" ");
}
One line with substr, indexOf and a variable on the fly ;-)
function inName(inputName) {
return inputName.substr(0, (index = inputName.indexOf(' '))) + inputName.substr(index).toUpperCase();
}
Here's another option which avoids the regular expression:
function inName(inputName) {
return inputName.split(' ').map(function(v,i){return i?v.toUpperCase():v;}).join(' ');
}
This does the same split as the original code, then maps the parts to a function which returns the value at index 0 unchanged but the value at index 1 in upper case. Then the two results are joined back together with a space.
As others have said, a longer, clearer version is better in practice than trying to come up with a clever one-liner. Defining a function inside the return statement feels like cheating anyway ;-)
Something like this almost seems like it belongs on Code Golf, but here's my take:
function inName(inputName) {
return inputName.replace(/ .*/,function(m) {return m.toUpperCase();});
}
Interesting. Here is my take on the problem
function justDoIt(str){
return [str = str.split(" ") , str.pop().toUpperCase()].join(" ");
}
Creates a new array, str is split and reassigned as an array, and the first item of the new array, then the second new array item pops the last word, makes it uppercase, puts it into the new array. Then joins the array [["wordOne"],"WORDTWO"].join(" ")

how can I fix this regular expression function?

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.

Creating AST with OMetaJS that includes token value and position

I'm trying to parse a DSL with OMetaJS and produce an AST that includes a token value as well as it's index in the original stream.
I know I can use the Index Capture Rule syntax ( #<rule> ) to give me an object containing the indices framing the token but is it possible to capture that as well as the token value?
E.g for the grammar:
export ometa Test {
start = #<identifier>,
identifier = (letter | digit)+
}
Parsing "Bob" gives:
{ fromIdx : 0, toIdx : 3 }
If I remove the '#' from 'identifier' then parsing gives "Bob" as the result. What I'd ideally like to get is combination of the two:
{ fromIdx : 0, toIdx : 3, value: 'Bob' }
I could of course hack the source, but is there a better way to do this?
I want to have both value and position because I'm trying to create a visual representation of the DSL which allows editing of identifier names for example. In this case I need to know where in the original source the identifier appeared so I can modify it.
I think what you're asking for is pretty useful, and probably deserves to have its own syntactic sugar. I'll definitely think about it. In the meantime, you could do something like this:
ometa Test {
parse :r = #<apply(r):value>:node !(node.value = value) -> node,
identifier = (letter | digit)+,
start = parse("identifier")
}
Hope that helps!
Given that you want the thing, and the span, what about using the peek operator &? That will return the token, but not consume the input. So perhaps something like
spannedThing = (&identifier:token #identifier:span) -> combineThemSomehow(token, span)
might do what you want? (Warning: my OMeta's rusty; the above might not use correct grammar.) You could turn that into a parameterised rule.

Categories

Resources