Replace individual symbols in a set - javascript

Is there a simplified way in JavaScript + Reg-Ex to replace all occurrences of each symbol in a set with its alternative symbol?
Example:
"Test: 1, 2, 3 and 1".replace("123", "ABC");
// we need to get: "Test: A, B, C and A";
I mean, is there any Reg-Ex trick to avoid a for-loop here? And anyway, what would be the most efficient way to do it?
Provisions:
In my task the set of symbols is usually very short (could even be 3 symbols) and it is static, not dynamic, very similar to the example shown.
Sometimes a symbol needs to be replaced with an empty '', i.e. removed.

You could build out your replacements using an Object Literal.
var map = {'1':'A', '2':'B', '3':'C'};
str = str.replace(/[123]/g, function(k) {
return map[k];
});
Or create a custom function using a map for this:
function _replace(str, map) {
var re = new RegExp('['+Object.keys(map).join('')+']','g');
return str.replace(re, function(x) { return map[x] });
}

Related

How to split ``(Backtick string) on each instance of ${variable}

So my question is how i can split the a string with backtick on each instance of variable.
I tried with \${.*?} but this will not work because ${variable} will be replaced by variable values first and than the split function will be executed.
Any idea how to do it ?
let a = 2
let b = 4
let x = `Superman${a}hello${b}one more`.split(/\${.*?}/g)
console.log(x)
On side not: I don't want a solution with wrapping it to " or '.
console.log('`Superman${a}hello${b}one more`'.split(/\${.*?}/g))
After the line executes, there is no way to get the original template string. However, you can use a tag function/tagged template literal to get the parts of the string, including the substitution values:
function Test() {
console.log(arguments)
return arguments.length - 1
}
let a = 2
let b = 4
let c = Test `Superman${a}hello${b}one more`
console.log(`This template string has ${c} substituted values`)
To clarify my comment to the original question here is an example of what the default Template Literal Function does:
function defaultTemplateLiteralFn(strs, ...args) {
return strs.map((str, idx) => str+(args[idx]||'')).join('');
}
const test = "special test";
const a = 10;
const b = 432;
console.log(`This is a ${test}. "${a}+${b}=${a+b}"`)
console.log(defaultTemplateLiteralFn`This is a ${test}. "${a}+${b}=${a+b}"`)
When you use a tagged template (IE: You don't provide a function to handle the template literal) The the language provides a default function that does something similar to what I do in my function defaultTemplateLiteralFn above. It returns the combined parts of the string with the values.
The example function takes each part of the string and puts the appropriate value after the string. If there is no value then it uses a blank string.
One way i have done is using template literal. i have seen this is being used in a in a library called styled-components which allows us to write css with js.
Would love to see other methods if there are any ?
function splitOnVariable(str, age){
// first argument to function will always be array of strings provided in input string.
return str
}
let a = 1;
let b = 2;
console.log(splitOnVariable`hello${a} break me on variable${b} !!!`)

Functional programming dictionary character replace, keyboard layout fixer

Let say we want to fix text that was written on a AZERTY(or Dvorak, or another language layout) keyboard, as if it was a regular QWERTY one. We want to replace certain characters on corresponding ones.
So we have a dictionary, that looks similar to this:
const dic = {
q: a,
z: w,
}
But the dictionary is big, for every character. I'm searching for a way to do this not using for loops, using advantages of latest javascript changes, maybe with .replace() or .map() or anything you can suggest.
You don't need a big dictionary since a lot of the keys on AZERTY are in the same place: only make a map for the keys that are different and return the input if no mapping exists:
const dict = {
q: "a",
w: "z"
// e, r, t, y are in the same place, for example...
};
console.log(
"qwerty".split("") // Explode the string to an array
.map(letter => dict[letter] || letter) // Map inputs
.join("") // output a string
);
// Generate a reverse mapping
const reverse_dict = {};
Object.keys(dict).forEach(key => reverse_dict[dict[key]] = key);
console.log(
"azerty".split("")
.map(letter => reverse_dict[letter] || letter)
.join("")
);
Note that with arrow functions:
You do not need parenthesis around the parameter list if there is only one parameter.
If you omit the {} around the function body, you can also omit the return keyword and the body will return the value of the last (only) expression (save for a void parameter, which is a set of empty brackets () which you'll see in places like setTimeout).
A common misconception about const is that you can't update an array or object after it's initialized, but that's not the case. What you can't do is assign the variable to something else (like const o = {}; o = "")

Function to match string to one of many regex?

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?

Javascript replace with $1 as var

I have the following situation:
There is a certain string that contains some vars, such as:
var string = '/page/{id}/{title}';
Now, I want to be able to replace {id} and {title} with the vars from the following array:
var arr = {'id':10, 'title':'test-page'};
I came up with this little regex:
string.replace ( /{([a-zA-Z0-9]+)}/g , '$1' );
Which, as expected, just returns this:
/page/id/title
So I tried this:
string.replace ( /{([a-zA-Z0-9]+)}/g , arr [ '$1' ] );
But that returns a
/page/undefined/undefined
Now, I understand that something like this would be possible with a loop et cetera, but it would be nice to have a one-liner for this. I am not very used to JS, so I hope that there is some function or option that I am unaware of that helps me out with this :).
Best regards!
Try something like this:
var arr = {'id':10, 'title':'test-page'};
'/page/{id}/{title}'.replace(/\{([\w\d]+?)\}/g, function(a, b) {
return arr[b] || '';
});
If you use this replace thing often I would create a String helper prototype method. For example:
String.prototype.template = function(data) {
return this.replace(/\{([\w\d]+?)\}/g, function(a, b) {
return data[b] || '';
});
};
and use it like this:
'/page/{id}/{title}'.template(arr);
According to MDN article,
Because we want to further
transform the result of the match before the final substitution is
made, we must use a function. This forces the evaluation of the match
prior to the toLowerCase() method. If we had tried to do this using
the match without a function, the toLowerCase() would have no effect.
(In the text above, replace toLowerCase() with "accessing property in object")
Then, you can use
function replacer(match, p1, p2, p3/*, ...*/, offset, string){
return arr[p1];
}
var arr = {'id':10, 'title':'test-page'};
'/page/{id}/{title}'.replace(/\{([\w\d]+?)\}/g, replacer);

JavaScript Function arguments

I am trying to create a function that deserialises a JSON object and creates some functions, but I want to be able to specify a variable set of arguments.
For example, in JSON I want to specify something like:
{
"handler" :
{
"args" : ["evt","value"],
"content" : "console.log(value);"
}
}
And when I parse the object, I will do something like:
var myFunction = new Function(handler.args,handler.content);
But the challenge is that each argument is supposed to be a n strings followed by the content of the function as the last argument. Is there any easy way of specifying n number of arguments in a new Function()?
To solve the technically issue: You can use apply [docs].
handler.args.push(handler.content);
var myFunction = Function.apply(null, handler.args);
However the question is why you are doing something like this? What is the context? Spontaneously I would say you should consider another solution for whatever problem you are trying to solve ;)
According to MDN
Parameters
arg1, arg2, ... argN
Names to be used by the function as formal argument names. Each must be
a string that corresponds to a valid
JavaScript identifier or a list of
such strings separated with a comma;
for example "x", "theValue", or "a,b".
So the arguments list can either be one or more strings seperated by commas, or just one string with each identifier in it seperated by commas.
Also since
['evt', 'value'].toString() == 'evt,value'
Simply passing your handler.args array as the first argument to the new Function constructor should work exactly as you want it to
new Function(handler.args, handler.content);
Internally, new Function casts every argument to a string if it is not already one. So conceivably something like this would also work
new Function({ toString: function() { return 'a,b,c' } }, 'return a+b+c');
Not that I'm suggesting you do anything silly like that.
This works in every browser I've tried including IE
I think the simplest route would be to combine the 2 properties. Then use apply to construct the function.
var x = {
"handler" :
{
"constructorArgs" : [
"evt",
"value",
"alert(value);"
]
}
};
var f = Function.apply(undefined, x.handler.constructorArgs);
f(1, 2);
To keep it similar you can use Array.prototype.concat.
var x = {
"handler" :
{
args: [ "evt", "value" ],
content : "alert(value);"
}
};
var f = Function.apply(undefined, x.handler.args.concat(x.handler.content));
f(1, 2);
Can;t you just make the body of your functions work with the arguments property?
http://jsfiddle.net/9XcEb/
var add = new Function(
"var total=0;"+
"for (var i=0; i < arguments.length; i++) {"+
"total+=arguments[i]"+
"};"+
" return total"
);
alert(add(3,4,5,6));

Categories