JavaScript Replace all odd behavior - javascript

I want this code:
function renderTemplate(temp,content){
for (var i in temp){
replace = new RegExp("["+i+"]",'g');
content = content.replace(i,temp[i]);
}
return content;
}
var temp = {'status':'ok','id':150};
var content = "your status is [status], again! your status is [status], and your id is [id], yes[id]";
alert(renderTemplate(temp,content));
To genrate me this string:
your status is ok, again! your status is ok, and your id is 150, yes 150
Instead, I get:
your ok is [status], again! your status is [status], and your 150 is [id], yes[id]
Look where the ok was placed....
you can run it here: http://jsfiddle.net/v9vzd/
Thanks

Although Adrian Lang's fine answer should get you going, I would argue that you're not taking the best approach. Compiling regexes from a variable can be awkward when it comes to escaping, and it's generally slower performance-wise.
If it were me, I would take advantage of passing a function to replace():
function renderTemplate(temp, content) {
return content.replace(/\[([^[\]+)\]/g, function ($0, key) {
return temp[key];
});
}
Working demo: http://jsfiddle.net/AKsHb/
This works because the sub-expression capture, ([^\]]+) is passed to the replacing function as the second argument — labelled key in our function above — and this matches anything between a literal [ and ].

Try the following code:
function renderTemplate(temp,content){
for (var i in temp){
replace = new RegExp("\\["+i+"\\]",'g');
content = content.replace(replace,temp[i]);
}
return content;
}
var temp = {'status':'ok','id':150};
var content = "your status is [status], again! your status is [status], and your id is [id], yes[id]";
alert(renderTemplate(temp,content));
You didn’t use the RegExp object you created. Furthermore, square brackets create a character class, so oyu have to escape the square bracket (and in the RegExp constructor call, you have to escape the escaping backslash, so it is two backslashes).

Related

why javascript regex is throwing error for special characters even after using '\'?

I am trying to catch invalid operators passed to eval() function so that it can display invalid expression on screen but it's not working. Is there something I am missing? sorry if this sounds silly but I am beginner to JavaScript.
function evaluating(el){
var invalidOperators = ['//','**','+/','/+','+*','*+','-/','/-','-*','/*','*/'];
var i;
for(i=0;i<invalidOperators.length;i++){
if(el.search(invalidOperators[i])!= -1){
document.getElementById('display').value = 'INVALID SYNTAX';
}
else{
document.getElementById('display').value = eval(el);
}
}
}
I tried adding \ to all strings in invalidOperators as for special characters of regex but it's still not working.
If you don't break the loop with break;, an invalid string can be found, but immediately after that, the next invalid string isn't found, so in the end you don't get the INVALID SYNTAX you're expecting, and that's a false negative.
I would simplify the function and write something like below. Your function should only do one thing, that is, return true or false (depending whether the string is valid or not). Then, use this function inside another function that does only one thing, that is, write 'INVALID SYNTAX' in a div. The smaller and more specialized a function, the better.
const invalidOperators = ['//','**','+/','/+','+*','*+','-/','/-','-*','/*','*/'];
// returns true if the string to test contains any of the elements in the invalidOperators array
const isInvalid = toTest => invalidOperators.some( e => toTest.includes(e) );
const checkInvalid = event => output.innerHTML = isInvalid(event.target.value) ? "INVALID!!" : "Okay.";
<input onkeyup="checkInvalid(event)"/>
<div id="output"></div>

.toLowerCase() / .toUpperCase() not working

I'm trying to get better at javascript through codewars.com katas, and I came across an exercice in which things like element[i]=element[i].toLowerCase() doesn't change anything at all.
I would like to have some help with my code, here is the exercice's instructions followed by my code:
(Please note that I'm not very experienced with JS so the code may not be perfect at all)
A string is considered to be in title case if each word in the string
is either:
(a) capitalised (that is, only the first letter of the word
is in upper case) or
(b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.
Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space.
Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.
Arguments:
First argument (required): the original string to be converted.
Second argument (optional): space-delimited list of minor words that must always be lowercase except for the first word in the string. The JavaScript/CoffeeScript tests will pass undefined when this argument is unused.
function titleCase(title, minorWords) {
if(title.length==0){return ""}
var titlesplit = title.split(" ")
if(minorWords){
minorWords=minorWords.split(" ")
}
var solutionstring = ""
titlesplit.forEach(element => myfunction(element,minorWords))
solutionstring[0] = solutionstring[0].toUpperCase()
return solutionstring
function myfunction(element,minorWords){
var elementlength= element.length
var i=0
if(minorWords && minorWords.includes(element)){
for(i;i<elementlength;i++){
element[i]=element[i].toLowerCase()
}
}else {
for(i;i<elementlength;i++){
if(i==0){element[i]=element[i].toUpperCase()}
else{element[i]=element[i].toLowerCase()}
}
}
if(solutionstring.length==0){solutionstring=solutionstring+element}else{solutionstring=solutionstring+" "+element}
return
}
}
As pointed out in comments, Strings are immutable in JavaScript.
Additionally, for searching use Maps instead of includes.
Likewise you can see what Set in JavaScript is and easily use Set here.
Added comments for you better understanding.
function titleCase(title, minorWords) {
// Use === for comparison
// Prefer using curly braces even for single statements
if (title.length === 0) {
return "";
}
var titlesplit = title.split(" ");
// Maps/Objects give O(1) search compared to arrays O(n)
// Key,value pairs - similar to dictionary
var minorWordsMap = {};
minorWords.split(" ").forEach(i => minorWordsMap[i.toLowerCase()] = true);
var finalWords = titlesplit.map((element, index) => convertCase(element, index));
finalWords[0] = toPascalCase(finalWords[0]);
return finalWords.join(" ");
function toPascalCase(s) {
s = s.split("");
s[0] = s[0].toUpperCase();
return s.join("");
}
function convertCase(element, index) {
const lElement = element.toLowerCase();
// If element is part of exception words, ignore
if(index !== 0 && minorWordsMap[lElement]) {
return element;
}
// If first element or not in exception list, send Title case
return toPascalCase(lElement);
}
}

Javascript: Check if any elements in an array contain a part of a string

I have an array of "banned domains", and I'm trying to find an easy way to check if a particular email is from one of those domains. Consider the following:
var bannedDoms = ["gmail.com", "hotmail.com", ".le.salesforce.com"]
if(bannedDoms.indexOf(email.split("#")[1]) === -1){
// It's a good domain!
}
This works fine, except for the last example, as the salesforce emails are from weird domains like emailtosalesforce#t-1l9sefi2sef5wlowk59bvm0uuh78mkdfuhioamfu7vxv8agjjh.o-h7zieac.na17.le.salesforce.com - the common factor being that they all have .le.salesforce.com in the address.
Searching via Array.prototype.indexOf() is quite an elegant solution and I'd like to use something similar if possible - but to also catch parts of strings, rather than a whole string match.
What's the most efficient and simple way to do this in Javascript?
I would go for a regex:
/gmail\.com|hotmail\.com|\le\.salesforce\.com/.test("emailtosalesforce#t-1l9sefi2sef5wlowk59bvm0uuh78mkdfuhioamfu7vxv8agjjh.o-h7zieac.na17.le.salesforce.com")
A fiddle is here
var bannedDoms = ["gmail.com", "hotmail.com", ".le.salesforce.com"];
r=new RegExp(bannedDoms.map(function(x){ return x.replace(/\./g,'\\.') }).join("|"));
Explanation:
You could simply build up a regular expression, taking each banned domain and combine them with or. The simplest form would be a|b, read a or b. In principle gmail.com or hotmail.com would become gmail.com|hotmail.com - with one exception: . is a special character in a regular expression meaning any character. To cirumvent this, we need to escape the dot to \..
r=new RegExp(bannedDoms.map(function(x){ return x.replace(/\./g,'\\.') }).join("|"));
Array.prototype.map() is a function, which applies a function onto each element of an array - returning the resulting array.
The map-part does nothing more than replacing every occuring . with an escaped version \..
Array.prototype.join() joins the resulting array-elements with a pipe = or.
Thanks #torazaburo
I think you will have to iterate and test the domains like
var bannedDoms = ["gmail.com", "hotmail.com", ".le.salesforce.com"];
function isBanned(email) {
var domain = email.split("#")[1];
var banned = bannedDoms.some(function(value) {
return domain.indexOf(value) > -1;
})
if (!banned) {
// It's a good domain!
}
snippet.log(email + ' : ' + banned);
}
isBanned('asdf#gmail.com');
isBanned('asdf#hotmail.com');
isBanned('asdf#.le.salesforce.com');
isBanned('asdf#abc.com');
isBanned('asdf#test.com');
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Probably a good candidate for the endsWith simulation:
var bannedDoms = ["gmail.com", "hotmail.com", ".le.salesforce.com"];
var email1 = "emailtosalesforce#t-asd.o-h7zieac.na17.le.salesforce.com";
var email2 = "emailtosalesforce#t-asd.o-h7zieac.na17.le.salesforce.net";
console.log(bannedDoms.some(function (e) {
return email1.indexOf(e, email1.length - e.length) !== -1;
})); // true
console.log(bannedDoms.some(function (e) {
return email2.indexOf(e, email2.length - e.length) !== -1;
})); // false
I think you'd have to do a string indexOf, if you want to catch those.
So, You can try something like this..
var bannedDoms = ["gmail.com", "hotmail.com", ".le.salesforce.com"]
for(var i=0; i<bannedDoms.length; i++) {
if(email.indexOf(bannedDoms[i]) === -1){
// It's a good domain!
}
}

How to avoid parsing address as float in Javascript

I am working on javascript code that parses a tab delimited document. In order to facilitate searching I need to convert those properties that are a number to a float. However, mixed fields (like an address) should maintain the status of a String.
for(var i2=0;i2<line1.length;i2++){
var test = local[i2];
if(! (typeof test === 'undefined')){
test = test.trim();
};
var parsed = parseFloat(test);
if(!isNaN(parsed)){
if(line1[i2] === "Site Address")
console.log("Number before:"+local[i2]+" After:"+parsed);
object[line1[i2]]=parsed;
}
else{
if(line1[i2] === "Site Address")
console.log("before:"+local[i2]+" After:"+test);
object[line1[i2]]=test;
}
}
This seems to work ok unless there are both numbers and chars like the following....
Number before:1752 E MAIN ST After:1752
Is there a way to do this where the above is not seen as explicitly a number?
You can use the unary + operator:
var parsed = +test;
The parseFloat() function is OK with strings that start with a valid number that's followed by non-numeric stuff, as you've discovered.
If that seems too "hackery" you can also use the Number constructor:
var parsed = Number( test );
You haven't provided very much test data, so answers may not be very good. You can try using a regular expression so that only things that look like numbers are treated as numbers, e.g.
var isNum = /^\d+(\.\d+)?$/;
var test = line1[i2];
parsed = isNum.test(test)? parseFloat(test) : test;
The variable "test" would probaby be better named "item" or "value" or similar.

Regular Expression: pull part from string. with JS

Hey all im not every good with regexp i was hoping someone could help.
ok so this is the sting "KEY FOUND! [ 57:09:91:40:32:11:00:77:16:80:34:40:91 ]"
And i need to pull "57:09:91:40:32:11:00:77:16:80:34:40:91", now this key can be meany length not just as written here and with or with out the ":"
now the second sting i would like to test and extract is: "[00:00:09] Tested 853 keys (got 179387 IVs)", i would like to pull "00:00:09" and "853" and "179387".
this would be the raw string http://regexr.com?31pcu or http://pastebin.com/eRbnwqn7
this is what im doing now.
var pass = new RegExp('KEY FOUND\!')
var tested = new RegExp('Tested')
var fail = new RegExp('\Failed. Next try with ([0-9]+) IVs')
var data="Look at the link i added"
if (tested.test(data)) {
self.emit('update', mac, {
'keys' : data.split('Tested ')[1].split(' keys ')[0],
'ivs' : data.split('got ')[1].split(' IVs')[0]
});
} else if (pass.test(data)) {
var key = data.split('KEY FOUND! [')[1].split(' ]')[0].split(':').join('');
} else if (fail.test(data)) {
console.log(data);
}
thanks all
Edit:
I have added more the the question to help with the answer
If it is always surrounded by [] then it is simple:
\[([\s\S]*)\]
This will match any characters enclosed by [].
See it in action here.

Categories

Resources