How can I partially hide email address like this in Javascript?
examplemail#domain.com => ex**pl**ai*#domain.com
I have modify the below code, but can get the result that I need, it's just return this result:
exam*******#domain.com
email.replace(/(.{4})(.*)(?=#)/, function (gp1, gp2, gp3) {
for (let i = 0; i < gp3.length; i++) {
gp2 += "*";
}
return gp2;
});
You could seach for a group of four characters and replace a group of two until you found an # sign-
const
mask = string => string.replace(
/(..)(.{1,2})(?=.*#)/g,
(_, a, b) => a + '*'.repeat(b.length)
);
console.log(mask('examplemail#domain.com'));
This would be one way to solve your problem:
function f(mail) {
let parts = mail.split("#");
let firstPart = parts[0];
let encrypt = firstPart.split("");
let skip = 2;
for (let i = 0; i < encrypt.length; i += 1) {
if (skip > 0) {
skip--;
continue;
}
if (skip === 0) {
encrypt[i] = "*";
encrypt[i + 1] = "*";
skip = 2;
i++;
}
}
let encryptedMail = `${encrypt.join("")}#${parts.slice(1)}`;
return encryptedMail;
}
Simply do this
function maskFunc(x) {
var res = x.replace(/(..)(.{1,2})(?=.*#)/g,
(beforeAt, part1, part2) => part1 + '*'.repeat(part2.length)
);
return res
}
console.log(maskFunc('emailid#domain.com'));
As a regex for the accepted answer, I would suggest making sure to match only a single # sign by making use of a negated character class [^\s#] matching any char except a whitespace char or an # itself.
This way you might also use it for multiple email addresses, because using (?=.*#) with multiple # signs can give unexpected results.
([^\s#]{2})([^\s#]{1,2})(?=[^\s#]*#)
Regex demo
In the pattern that you tried, you matched 4 times any char using (.{4}). Repeating 4 chars might be done using a positive lookbehind. Then you could get the match only without groups.
First assert a whitespace boundary to the left. Then start with an offset of 2 chars, optionally repeated by 4 chars.
Then match 1 or 2 chars, asserting an # to the right.
const partialMask = s => s.replace(
/(?<=(?<!\S)[^\s#]{2}(?:[^\s#]{4})*)[^\s#]{1,2}(?=[^\s#]*#)/g,
m => '*'.repeat(m.length)
);
console.log(partialMask("examplemail#domain.com"));
If you want to only replace the digits close to the # and allow it to add * base on the length, you can do this
const separatorIndex = email.indexOf('#');
if (separatorIndex < 3)
return email.slice(0, separatorIndex).replace(/./g, '*')
+ email.slice(separatorIndex);
const start = separatorIndex - Math.round(Math.sqrt(separatorIndex)) - 1;
const masked = email.slice(start, separatorIndex).replace(/./g, '*');
return email.slice(0, start) + masked + email.slice(separatorIndex);
Related
How to remove only the last dots in characters in jquery?
Example:
1..
1.2.
Expected result:
1
1.2
My code:
var maskedNumber = $(this).find('input.CategoryData');
var maskedNumberValue = $(maskedNumber).val().replace(/[^0-9.]/g, '').replace('.', 'x').replace('x', '.').replace(/[^\d.-]/g, '');
console.log(maskedNumberValue.slice(0, -1))
How do I solve this problem? Thanks
You can use regex replace for that:
function removeLastDot(value) {
return value.replace(/\.*$/, '')
}
console.log(removeLastDot('1..'))
console.log(removeLastDot('1.2.'))
In the example I use \.*$ regex:
$ - means that I want replace at the end of string
\.* - means that I want to match any number for . symbol (it is escaped cause . is special symbol in regex)
You can traverse the string with forEach and store the last index of any number in a variable. Then slice up to that variable.
let lastDigitIndex = 0;
for (let i = 0; i < str.length; i++) {
let c = str[i];
if (c >= '0' && c <= '9') lastDigitIndex = i;
};
console.log(str.slice(0, lastDigitIndex-1));
This will be an optimal solution.
maybe this can help.
var t = "1...";
while (t.substr(t.length - 1, 1) == ".") {
t = t.substr(0,t.length - 1);
}
import re
s = '1.4....'
# reverse the string
rev_s = s[::-1]
# find the first digit in the reversed string
if first_digit := re.search(r"\d", rev_s):
first_digit = first_digit.start()
# cut off extra dots from the start of the reversed string
s = rev_s[first_digit:]
# reverse the reversed string back and print the normalized string
print(s[::-1])
1.4
Add replace(/\.*$/g, '') to match one or more dots at the end of the string.
So your code would be like this:
var maskedNumberValue = $(maskedNumber).val().replace(/[^0-9.]/g, '').replace('.', 'x').replace('x', '.').replace(/[^\d.-]/g, '').replace(/\.*$/g, '');
I have a array of string and the patterns like #number-number anywhere inside a string.
Requirements:
If the # and single digit number before by hyphen then replace # and add 0. For example, #162-7878 => 162-7878, #12-4598866 => 12-4598866
If the # and two or more digit number before by hyphen then replace remove #. For example, #1-7878 => 01-7878.
If there is no # and single digit number before by hyphen then add 0. For example, 1-7878 => 01-7878.
I got stuck and how to do in JavaScript. Here is the code I used:
let arrstr=["#12-1676","#02-8989898","#676-98908098","12-232","02-898988","676-98098","2-898988", "380100 6-764","380100 #6-764","380100 #06-764"]
for(let st of arrstr)
console.log(st.replace(/#?(\d)?(\d-)/g ,replacer))
function replacer(match, p1, p2, offset, string){
let replaceSubString = p1 || "0";
replaceSubString += p2;
return replaceSubString;
}
I suggest matching # optionally at the start of string, and then capture one or more digits before - + a digit to later pad those digits with leading zeros and omit the leading # in the result:
st.replace(/#?\b(\d+)(?=-\d)/g, (_,$1) => $1.padStart(2,"0"))
See the JavaScript demo:
let arrstr=["#12-1676","#02-8989898","#676-98908098","12-232","02-898988","676-98098","2-898988", "380100 6-764","380100 #6-764","380100 #06-764"]
for(let st of arrstr)
console.log(st,'=>', st.replace(/#?\b(\d+)(?=-\d)/g, (_,$1) => $1.padStart(2,"0") ))
The /#?\b(\d+)(?=-\d)/g regex matches all occurrences of
#? - an optional # char
\b - word boundary
(\d+) - Capturing group 1: one or more digits...
(?=-\d) - that must be followed with a - and a digit (this is a positive lookahead that only checks if its pattern matches immediately to the right of the current location without actually consuming the matched text).
Using the unary operator, here's a two liner replacer function.
const testValues = ["#162-7878", "#12-4598866", "#1-7878", "1-7878"];
const re = /#?(\d+?)-(\d+)/;
for(const str of testValues) {
console.log(str.replace(re, replacer));
}
function replacer(match, p1, p2) {
p1 = +p1 < 10 ? `0${p1}` : p1;
return `${p1}-${p2}`;
}
let list_of_numbers =["#1-7878", "#162-7878", "#12-1676","#02-8989898","#676-98908098","12-232","02-898988","676-98098","2-898988"]
const solution = () => {
let result = ''
for (let number of list_of_numbers) {
let nums = number.split('-')
if (nums[0][0] == '#' && nums[0].length > 2) {
result = `${nums[0].slice(1, number.length-1)}-${nums[1]}`
console.log(result)
} else if (nums[0][0] == '#' && nums[0].length == 2) {
result = `${nums[0][0] = '0'}${nums[0][1]}-${nums[1]}`
console.log(result)
} else {
console.log(number)
}
}
}
I think a simple check is what you should do with the match function.
let arrstr=["#12-1676","#0-8989898","#676-98908098","12-232","02-898988","676-98098","2-898988"];
const regex = /#\d-/g;
for(i in arrstr){
var found = arrstr[i].match(regex);
if(found){
arrstr[i]=arrstr[i].replace("#","0")
}else{
arrstr[i]=arrstr[i].replace("#","")
}
}
console.log(arrstr);
or if you really want to stick with the way you have it.
let arrstr=["#12-1676","#02-8989898","#6-98908098","12-232","02-898988","676-98098","2-898988"]
for(let st of arrstr)
console.log(st.replace(/#(\d)?(\d-)/g ,replacer))
function replacer(match, p1, p2, offset, string){
let replaceSubString = p1 || "0";
replaceSubString += p2;
return replaceSubString;
}
remove the '?' from the regex so its not #? but just #
I use the custom JS code heavily in Zapier. When arrays are imported into this step, Zapier converts it it into a literal string, i.e:
['BigBoatBob, XL-1', 'LittleBoatMike, M-2', 'SunkBoatCheney, XS-9']
turns into:
'BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9'
I've created a function to parse out the array items (accounting for textual commas) but it seems very, VERY sloppy. Anyone have any suggestions to refine / shorten/ make look more professional? Thanks for helping me to further my abilities :)
var array = splitArray('BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9');
function splitArray(x) {
const pos = [];
const POS = [];
const res = [];
for (var i = 0; i < x.length; i++) {
if (x[i] == ',') pos.push(i);
}
for (i = 0; i < pos.length; i++) {
let a = x.slice(pos[i]);
if (!a.startsWith(', ')) POS.push(pos[i]);
}
POS.push(x.length);
POS.unshift(0);
for (i = 0; i < POS.length - 1; i++) {
res.push(x.slice(POS[i], POS[i+1]));
}
return res.map(x => {
if (x.startsWith(',')) {
return x.slice(1);
} else {
return x;
}
});
}
console.log(array);
If you can rely on the spaces after the commas within the strings and rely on their not being one between the strings, you can use split with the regular expression /,(?! )/ which says "a comma not followed by a space:"
const str = 'BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9';
const array = str.split(/,(?! )/);
console.log(array);
If you can't rely on that but you can rely on the format of the XL-1 and such, you can do it with an exec loop (or with an up-to-date JavaScript engine or a polyfill, with matchAll):
const str = 'BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9';
const array = [];
const rex = /(.*?,\s*[A-Z]{1,2}-\d)\s*,?/g;
let match;
while ((match = rex.exec(str)) !== null) {
array.push(match[1]);
}
console.log(array);
The regular expression /(.*?,\s*[A-Z]{1,2}-\d)\s*,?/g means:
.*? any number of any character, non-greedy
, a comma
\s* zero or more whitespace characters
[A-Z]{1,2} one or two letters from the range A-Z
- a dash
\d a single digit (use \d+ if there can be more than one)
All of the above is in a capture group
,? an optional comma following it
I would use Array.reduce:
var s = 'BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9'
var result = s.split(',').reduce((acc, curr, i) => {
if(i % 2 == 0) { acc[i] = curr }
else { acc[i - 1] += curr }
return acc
}, []).filter(x => x)
console.log(result)
Shorthand,
function splitIt(str) {
return str.split(',').reduce((a,v,i)=>((i % 2 == 0)?a.push(v):a[a.length-1]=a[a.length-1]+","+v,a),[]);
}
// Example
let str = `BigBoatBob, XL-1,LittleBoatMike, M-2,SunkBoatCheney, XS-9`;
console.log(splitIt(str));
I'm trying to figure out how to remove every second character (starting from the first one) from a string in Javascript.
For example, the string "This is a test!" should become "hsi etTi sats!"
I also want to save every deleted character into another array.
I have tried using replace method and splice method, but wasn't able to get them to work properly. Mostly because replace only replaces the first character.
function encrypt(text, n) {
if (text === "NULL") return n;
if (n <= 0) return text;
var encArr = [];
var newString = text.split("");
var j = 0;
for (var i = 0; i < text.length; i += 2) {
encArr[j++] = text[i];
newString.splice(i, 1); // this line doesn't work properly
}
}
You could reduce the characters of the string and group them to separate arrays using the % operator. Use destructuring to get the 2D array returned to separate variables
let str = "This is a test!";
const [even, odd] = [...str].reduce((r,char,i) => (r[i%2].push(char), r), [[],[]])
console.log(odd.join(''))
console.log(even.join(''))
Using a for loop:
let str = "This is a test!",
odd = [],
even = [];
for (var i = 0; i < str.length; i++) {
i % 2 === 0
? even.push(str[i])
: odd.push(str[i])
}
console.log(odd.join(''))
console.log(even.join(''))
It would probably be easier to use a regular expression and .replace: capture two characters in separate capturing groups, add the first character to a string, and replace with the second character. Then, you'll have first half of the output you need in one string, and the second in another: just concatenate them together and return:
function encrypt(text) {
let removedText = '';
const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
// in case the match was at the end of the string,
// and the string has an odd number of characters:
if (!secondChar) secondChar = '';
// remove the firstChar from the string, while adding it to removedText:
removedText += firstChar;
return secondChar;
});
return replacedText1 + removedText;
}
console.log(encrypt('This is a test!'));
Pretty simple with .reduce() to create the two arrays you seem to want.
function encrypt(text) {
return text.split("")
.reduce(({odd, even}, c, i) =>
i % 2 ? {odd: [...odd, c], even} : {odd, even: [...even, c]}
, {odd: [], even: []})
}
console.log(encrypt("This is a test!"));
They can be converted to strings by using .join("") if you desire.
I think you were on the right track. What you missed is replace is using either a string or RegExp.
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match. If pattern is a string, only the first occurrence will be replaced.
Source: String.prototype.replace()
If you are replacing a value (and not a regular expression), only the first instance of the value will be replaced. To replace all occurrences of a specified value, use the global (g) modifier
Source: JavaScript String replace() Method
So my suggestion would be to continue still with replace and pass the right RegExp to the function, I guess you can figure out from this example - this removes every second occurrence for char 't':
let count = 0;
let testString = 'test test test test';
console.log('original', testString);
// global modifier in RegExp
let result = testString.replace(/t/g, function (match) {
count++;
return (count % 2 === 0) ? '' : match;
});
console.log('removed', result);
like this?
var text = "This is a test!"
var result = ""
var rest = ""
for(var i = 0; i < text.length; i++){
if( (i%2) != 0 ){
result += text[i]
} else{
rest += text[i]
}
}
console.log(result+rest)
Maybe with split, filter and join:
const remaining = myString.split('').filter((char, i) => i % 2 !== 0).join('');
const deleted = myString.split('').filter((char, i) => i % 2 === 0).join('');
You could take an array and splice and push each second item to the end of the array.
function encrypt(string) {
var array = [...string],
i = 0,
l = array.length >> 1;
while (i <= l) array.push(array.splice(i++, 1)[0]);
return array.join('');
}
console.log(encrypt("This is a test!"));
function encrypt(text) {
text = text.split("");
var removed = []
var encrypted = text.filter((letter, index) => {
if(index % 2 == 0){
removed.push(letter)
return false;
}
return true
}).join("")
return {
full: encrypted + removed.join(""),
encrypted: encrypted,
removed: removed
}
}
console.log(encrypt("This is a test!"))
Splice does not work, because if you remove an element from an array in for loop indexes most probably will be wrong when removing another element.
I don't know how much you care about performance, but using regex is not very efficient.
Simple test for quite a long string shows that using filter function is on average about 3 times faster, which can make quite a difference when performed on very long strings or on many, many shorts ones.
function test(func, n){
var text = "";
for(var i = 0; i < n; ++i){
text += "a";
}
var start = new Date().getTime();
func(text);
var end = new Date().getTime();
var time = (end-start) / 1000.0;
console.log(func.name, " took ", time, " seconds")
return time;
}
function encryptREGEX(text) {
let removedText = '';
const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
// in case the match was at the end of the string,
// and the string has an odd number of characters:
if (!secondChar) secondChar = '';
// remove the firstChar from the string, while adding it to removedText:
removedText += firstChar;
return secondChar;
});
return replacedText1 + removedText;
}
function encrypt(text) {
text = text.split("");
var removed = "";
var encrypted = text.filter((letter, index) => {
if(index % 2 == 0){
removed += letter;
return false;
}
return true
}).join("")
return encrypted + removed
}
var timeREGEX = test(encryptREGEX, 10000000);
var timeFilter = test(encrypt, 10000000);
console.log("Using filter is faster ", timeREGEX/timeFilter, " times")
Using actually an array for storing removed letters and then joining them is much more efficient, than using a string and concatenating letters to it.
I changed an array to string in filter solution to make it the same like in regex solution, so they are more comparable.
I want to swap element 0 by element 1 so element 1 become 0 idx and element 0 become 1 idx.
for instance Hello guys becomes eHllo ugys
my code is kind of tedious and it returns something like this eHll ougys it moves the last letter of a word to the first letter of the next word.
is there a way to do it without forloop?.
const tex = `Hello guys`;
const swap = str => {
let swapped = [];
strin = str.split('');
for (let i = 0; i < strin.length; i++) {
if (i < strin.length) {
swapped[i] = strin[i + 1];
swapped[i + 1] = strin[i];
i += 1;
} else {
swapped[i] = strin[i];
}
}
return swapped.join('');
}
console.log(swap(tex));
One option is to use a regular expression - capture one word character at the beginning of a word followed by another captured word character, and replace with those swapped capture groups:
const tex = `Hello guys`;
const Swap = str => str.replace(/\b(\w)(\w)/g, '$2$1');
console.log(Swap(tex));
This alternative splits the string by space.
Then, using the array, the function map converts the strings into the desired output.
let swap = s =>
s.split(/\s/).map(s => {
let split = s.split(''),
letters = [];
if (split.length > 1) { // This is for string with only one char
// Get the two chars -> He
// reverse them -> eH
letters = split.splice(0, 2).reverse();
}
return letters.join('') + split.join('');
}).join(' ');
console.log(swap("Hello guys"));
console.log(swap("Ele From S"));
You can also do it using split and join (without any regex):
const tex = `Hello guys`;
const strs = tex.split(' ')
const changed = strs.map(str => {
const s = str.split('')
const s1 = s[1]
const s0 = s[0]
s[0] = s1
s[1] = s0
return s.join('')
})
console.log(changed.join(' '))