Replacing multiple characters in a string with a string rewrites characters - javascript

I have a variable (in this example var str = "I!%1$s-I!%2$s TTL!%3$s";), in which I want to replace the % with elements from an array (var regex = ['aaa', 'bbb', 'ccc'];).
I google around a bit and found this solution, but I'm having trouble implementing it. My problem is that I want to replace a single character with multiple characters, and then continue the string, but this just overwrites the characters. I actually have no idea why.
Any help is appreciated, my code below
String.prototype.replaceAt = function(index, character) {
return this.substr(0, index) + character + this.substr(index + character.length);
}
var str = "I!%1$s-I!%2$s TTL!%3$s";
var regex = ['replace', 'replace', 'replace'];
//find position of %
var find = /%/gi,
result, pos = [];
while ((result = find.exec(str))) {
pos.push(result.index);
}
//replace % with regex elements
for (x = 0; x < pos.length; x++) {
str = str.replaceAt(pos[x], regex[x]);
}
document.write(str);

Use replacement function, like this
var str = "I!%1$s-I!%2$s TTL!%3$s";
var regex = ['[123]', '[456]', '[789]'];
console.log(str.replace(/%(\d+)/g, function(match, group1) {
return regex[parseInt(group1) - 1] + group1;
}));
// I![123]1$s-I![456]2$s TTL![789]3$s
The RegEx /%(\d+)/g matches anything of the pattern % followed by one or more digits. And it captures the digits as a group. Then the exact match and the group is passed to the function to get the actual replacement. In the function, you convert the group to a number with parseInt and return the respective value from the regex array.

Related

How to insert symbol when encountering duplicates in a string

Lets assume that I have this string: aabbc and between every character which is not equal to the prior character I want to insert a symbol.
Which would result in the following string: aa$bb$c
How can this be achived?
You can do that in following steps:
You can convert string to array using Spread Operator
Then use map() on it
Inside map() check if the element on next to current is not same as current letter then add $ at its end.
Use join() to make array a string.
Remove the last $ using slice() which is extra.
let str = 'aabbc';
let res = [...str].map((x,i,arr) => arr[i+1] !== arr[i] ? x + '$' : x).join('').slice(0,-1)
console.log(res)
You can also use RegExp and match()
let str = 'aabbc';
let res = str.match(/(.)(\1*)/g).join('$')
console.log(res)
Can be done with a single replace:
input.replace(/(.)(?!\1)(?=.)/g, "$1$$")
Explanation of the pattern:
. - matches any single character (except newline); let's call this character X.
(.) - capturing subpattern; captures X so that it can be referenced in the replacement string (explained below).
\1 - backreference; matches another character identical to X.
(?!\1) - negative look-ahead; matches only if the X matched so far, is not followed by another X.
(?=.) - positive look-ahead; matches only if the X matched so far, is followed by any other character; in other words, asserts that the line does not end here. Can be omitted if you don't mind having a trailing $ appended.
Explanation of the replacement string:
$1 - the X captured by the first capturing subpattern (see above).
$$ - a single $.
Example:
var input = "aabbc";
var out = input.replace(/(.)(?!\1)(?=.)/g, "$1$$");
console.log(out);
Maybe try to do:
var charArray = myString.split(''); //this should split the string in an array of the characters. ["a", "a", "b", "b", "c"]
var newString = "";
for (int i = 0; i < charArray.length -1; i++) { //I do length -1 so to not cause an IndexOutOfBoundException at charArrayi+1]
if (charArray[i] === charArray[i+1]) {
newString += charArray[i] + charArray[i+1] + "$";
}
}
Something like that maybe?
I haven't actually tested this, I just typed it in here.
But in my head this feels right. :)
const a = 'aabbc';
let last = '';
let str = '';
for (let i = 0; i < a.length; i += 1) {
str += a[i];
if (last === a[i]) {
str += '$';
}
last = a[i];
}
console.log(str);
You can do this by using simple for loop as mentioned below:
var string = "aabbc";
var checkChar = "";
for (let i = 0; i < string.length; i++) {
checkChar += string.charAt(i);
if (string.charAt(i - 1) === string.charAt(i)){
checkChar += "$";
}
}
console.log(checkChar)

regex (only 1 dot)

I have a regEx where I replace everything whats not a number:
this.value.replace(/[^0-9\.]/g,'');
how can i make sure it will only allow 1 dot
(the second dot will be replaced like the others)
(I know you can use input just number (thats not an option in this project for me))
You can use a simple trick of:
splitting a string by ., and then only joining the first two elements of the array (using .splice(0,2)) with a . and the rest with nothing
using a simple regex pattern to replace all non-digit and non-period characters: /[^\d\.]/gi
Here is an example code:
// Assuming that `yourString` is the input you want to parse
// Step 1: Split and rejoin, keeping only first occurence of `.`
var splitStr = yourString.split('.');
var parsedStr = splitStr[0];
if (splitStr.length) {
parsedStr = splitStr.splice(0, 2).join('.') + splitStr.join('');
}
// Step 2: Remove all non-numeric characters
parsedStr = parsedStr.replace(/[^\d\.]/gi, '');
Proof-of-concept example:
var tests = [
'xx99',
'99xx',
'xx99xx',
'xxxx999.99.9xxx',
'xxxx 999.99.9 xxx',
'xx99xx.xx99xx.x9',
'xx99xx.99x.9x',
'xx99.xx99.9xx'
];
for (var i = 0; i < tests.length; i++) {
var str = tests[i];
// Split and rejoin, keeping only first occurence of `.`
var splitStr = str.split('.');
var parsedStr = splitStr[0];
if (splitStr.length) {
parsedStr = splitStr.splice(0, 2).join('.') + splitStr.join('');
}
// Remove all non-numeric characters
parsedStr = parsedStr.replace(/[^\d\.]/gi, '');
console.log('Original: ' + str + '\nParsed: ' + parsedStr);
}
I resolved it with.
this.value = this.value.replace(/.*?(\d+.\d+).*/g, "$1");

How can I replace single digit numbers within a string without affecting 2 digit numbers in that string

I'm working to update this function which currently takes the content and replaces any instance of the target with the substitute.
var content = textArea.value; //should be in string form
var target = targetTextArea.value;
var substitute = substituteTextArea.value;
var expression = new RegExp(target, "g"); //In order to do a global replace(replace more than once) we have to use a regex
content = content.replace(expression, substitute);
textArea.value = content.split(",");
This code somewhat works... given the input "12,34,23,13,22,1,17" and told to replace "1" with "99" the output would be "992,34,23,993,22,99,997" when it should be "12,34,23,13,22,99,17". The replace should only be performed when the substitute is equal to the number, not a substring of the number.
I dont understand the comment about the regex needed to do a global replace, I'm not sure if that's a clue?
It's also worth mentioning that I'm dealing with a string separated by either commas or spaces.
Thanks!
You could do this if regex is not a requirement
var str = "12,34,23,13,22,1,17";
var strArray = str.split(",");
for(var item in strArray)
{
if(strArray[item] === "1")
{
strArray[item] = "99"
}
}
var finalStr = strArray.join()
finalStr will be "12,34,23,13,22,99,17"
Try with this
var string1 = "12,34,23,13,22,1,17";
var pattern = /1[^\d]/g;
// or pattern = new RegExp(target+'[^\\d]', 'g');
var value = substitute+",";//Replace comma with space if u uses space in between
string1 = string1.replace(pattern, value);
console.log(string1);
Try this
target = target.replace(/,1,/g, ',99,');
Documentation
EDIT: When you say: "a string separated by either commas or spaces"
Do you mean either a string with all commas, or a string with all spaces?
Or do you have 1 string with both commas and spaces?
My answer has no regex, nothing fancy ...
But it looks like you haven't got an answer that works yet
<div id="log"></div>
<script>
var myString = "12,34,23,13,22,1,17";
var myString2 = "12 34 23 13 22 1 17";
document.getElementById('log').innerHTML += '<br/>with commas: ' + replaceItem(myString, 1, 99);
document.getElementById('log').innerHTML += '<br/>with spaces: ' + replaceItem(myString2, 1, 99);
function replaceItem(string, needle, replace_by) {
var deliminator = ',';
// split the string into an array of items
var items = string.split(',');
// >> I'm dealing with a string separated by either commas or spaces
// so if split had no effect (no commas found), we try again with spaces
if(! (items.length > 1)) {
deliminator = ' ';
items = string.split(' ');
}
for(var i=0; i<items.length; i++) {
if(items[i] == needle) {
items[i] = replace_by;
}
}
return items.join(deliminator);
}
</script>

Regex to find matches except in last n characters of input

I have to replace the digits in the first (n-4) characters of credit card with '*'.
I am using following three lines of code.
var cardnumber = '1A2C3GF4DS84Ff';
last4digits = cardNumber.substring(cardNumber.length-4);
prevdigits = cardNumber.substring(0, cardNumber.length-4).replace(/[0-9]/g,'*');
$cache.cardNumber.val( prevdigits + last4digits);
Just wondering can I do it in just one line of code by using regex.
Use a look-ahead to ensure that there are at least four remaining characters after the digit. In other words, digits within the last four characters will not match:
var regexp = /\d(?=....)/g;
> cardnumber.match(regexp)
< ["1", "2", "3", "4"]
To replace with asterisks:
> cardnumber.replace(regexp, '*')
< "*A*C*GF*DS84Ff"
Information on look-aheads is here.
From here I got this code.
var text = '1ab2cb3cd4ab5cb6cd7';
var matches = text.match(/(\d)/g);
for (i=0; i<matches.length; i++) {
alert(matches[i]);
}
Actually, they wanted to extract digits too. I don't need to change the regex.
You can limit it to 5 by making the loop start with:
for (i=0; i<matches.length && i < 5; i++){
Just use (\d) and check it programmatically afterwards.
var y= x.replace(/\D/g, '').substring(0, 5);
The .replace() function can use a function as the replacement, and it will be called for each match. It can keep a counter and return something different based on the counter.
var str = '1A2C3GF4DS84Ff';
var digits = 0;
var newstr = str.replace(/\d/g, function(match) {
if (digits++ < 4) {
return '*';
} else {
return match;
}
});
document.write(newstr);
looks like following one does the job You need:
var text= '1A2B3C4D5E6F',
n = 5;
text = text.replace(/\d/g, function ($1){
return n-- ?'*' : $1
});

Regex to remove all characters that are repeated

I'm looking for a regex that will remove all characters that have been repeated in a string. I already solved this using a loop. Just wondering if there is a regex that can do the same.
this is what i have so far:
function onlyUnique(str) {
var re = /(.)(?=.*\1)/g
return str.replace(re, '');
}
This string:
"rc iauauc!gcusa_usdiscgaesracg"
should end up as this:
" !_de"
You can use Array#filter with Array#indexOf and Array#lastIndexOf to check if the element is repeated.
var str = "rc iauauc!gcusa_usdiscgaesracg";
// Split to get array
var arr = str.split('');
// Filter splitted array
str = arr.filter(function (e) {
// If index and lastIndex are equal, the element is not repeated
return arr.indexOf(e) === arr.lastIndexOf(e);
}).join(''); // Join to get string from array
console.log(str);
document.write(str);
well, no idea if regex can do that, but you could work it out using for loop, like:
function unikChars(str) {
store = [];
for (var a = 0, len = str.length; a < len; a++) {
var ch = str.charAt(a);
if (str.indexOf(ch) == a && str.indexOf(ch, a + 1) == -1) {
store.push(ch);
}
}
return store.join("");
}
var str = 'rc iauauc!gcusa_usdiscgaesracg';
console.log(unikChars(str)); //gives !_de
Demo:: jsFiddle
Your regex searches pairs of duplicated characters and only removes the first one. Therefore, the latest duplicate won't be removed.
To address this problem, you should remove all duplicates simultaneously, but I don't think you can do this with a single replace.
Instead, I would build a map which counts the occurrences of each character, and then iterate the string again, pushing the characters that appeared only once to a new string:
function onlyUnique(str) {
var map = Object.create(null);
for(var i=0; i<str.length; ++i)
map[str[i]] = (map[str[i]] || 0) + 1;
var chars = [];
for(var i=0; i<str.length; ++i)
if(map[str[i]] === 1)
chars.push(str[i]);
return chars.join('');
}
Unlike indexOf, searches in the hash map are constant on average. So the cost of a call with a string of n characters will be n.
If you want to do it with a regex, you can use your own regex with a callback function inside a replace.
var re = /(.)(?=.*\1)/g;
var str = 'rc iauauc!gcusa_usdiscgaesracg';
var result = str;
str.replace(re, function(m, g1) {
result = result.replace(RegExp(g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), '');
});
document.getElementById("r").innerHTML = "'" + result + "'";
<div id="r"/>
The idea is: get the duplicated character, and remove it from the input string. Note that escaping is necessary if the character might be a special regex metacharacter (thus, g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") is used).
Another idea belongs to Washington Guedes in his deleted answer, I just add my own implementation here (with removing duplicate symbols from the character class and escaping special regex chars):
var s = "rc iauauc!gcusa_u]sdiscgaesracg]";
var delimiters= '[' + s.match(/(.)(?=.*\1)/g).filter(function(value, index, self) { // find all repeating chars
return self.indexOf(value) === index; // get unique values only
}).join('').replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ']'; // escape special chars
var regex = new RegExp(delimiters, 'g'); // build the global regex from the delimiters
var result = s.replace(regex, ''); // obtain the result
document.getElementById("r2").innerHTML = "'" + result + "'";
<div id="r2"/>
NOTE: if you want to support newline symbols as well, replace . with [^] or [\s\S] inside the regex pattern.
function onlyUnique(str) {
// match the characters you want to remove
var match = str.match(/(.)(?=.*\1)/g);
if (match) {
// build your regex pattern
match = '[' + match.join('') + ']';
}
// if string is already unique return the string
else {
return str
}
// create a regex with the characters you want to remove
var re = new RegExp(match, 'g');
return str.replace(re, '');
}

Categories