replacing special characters with other character from array in js - javascript

I would like to get rid of special characters in a string by comparing each of it's character to a character in an array and replacing it with a matching one. The function below does not throw any errors but keeps returning the string unchanged
var name = "przykład";
// the characters i'm looking for in a string:
var charList = ["Ą","ą","Ć","ć","Ę","ę","Ł","ł","Ó","ó","Ś","ś","Ź","ź","Ż","ź"];
// the characters i'd like to replace them with:
var replaceList = ["A","a","C","c","E","e","L","l","O","o","S","s","Z","z","Z","z"];
var limit = name.length;
for (i = 0; i < limit; i++){
for(var j in charList){
name.charAt(i) === charList[j] ? name.replace(name.charAt(i), replaceList[j]) : "";
}
}
return name;
I know this question will be most likely closed as "too localized" and it's propably a stupid and easy mistake i've made but still I would really appreciate any help with this

Usually, the result of the replace function is returned as a new String object in most of the programming languages. You should change your code to this:
if (name.charAt(i) === charList[j])
name = name.replace(name.charAt(i), replaceList[j]);
Also, since the replace function will replace all the occurrences of that character, you could change your algorithm a little bit.

You can put the mapping into an object, which has the advantage of being a bit easier to maintain since the character and its replacement are adjacent in the object, rather than trying to align position in an array.
e.g.
var name = "przykłąd Ęś";
// Object of characters to replace and their replacement values
var charList = {'Ą':'A', 'ą':'a', 'Ć':'C', 'ć':'c', 'Ę':'E', 'ę':'e',
'Ł':'L', 'ł':'l', 'Ó':'O', 'ó':'o', 'Ś':'S', 'ś':'s',
'Ź':'Z', 'ź':'z', 'Ż':'Z', 'ż':'z'};
// For each character in the string, search for it in charList and if found,
// replace it with the value
alert(
name + '\n' + name.replace(/./g, function(c) {return c in charList? charList[c] : c})
);
There is likely something cleverer that can be done with char codes, but I can't think of it right now.
Edit 2017
Fixed last character mapping—thanks #MarekSkiba. :-)

Here my solution...
var cleanName = function(str) {
if ($.trim(str) == '') return str; // jQuery
str = $.trim(str).toLowerCase();
var special = ['&', 'O', 'Z', '-', 'o', 'z', 'Y', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', '.', ' ', '+', '\''],
normal = ['et', 'o', 'z', '-', 'o', 'z', 'y', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'd', 'n', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', '_', '_', '-', '-'];
for (var i = 0; i < str.length; i++) {
for (var j = 0; j < special.length; j++) {
if (str[i] == special[j]) {
str = str.replace(new RegExp(str[i], 'gi'), normal[j]);
}
}
}
str = str.replace(/[^a-z0-9_\-]/gi, '_');
str = str.replace(/[\-]{2,}/gi, '_');
str = str.replace(/[\_]{2,}/gi, '_');
return str;
};
console.log(cleanName('l\'éléphant')); // "l-elephant"

Related

I just want to sort my words from array alphabetically by 1st letter and then by 2nd letter according to my given pattern which matched by 1st letter

♦ pattern:
e,b,c,d,i,f,g,h,o,j,k,l,m,n,u,p,q,r,s,t,a,v,w,x,y,z
I want to sort my words from arr alphabetically by 1st letter and then by 2nd letter of a similar word matched by 1st letter according to my given pattern.
['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd']
♦ output should be:
['aibcdh', 'aobcdh', 'aabcdh', 'aacbdh', 'cighjd', 'cfghjd' ]
♦ or:
aibcdh
aobcdh
aabcdh
aacbdh
cighjd
cfghjd
My Code here:
let pattern = ['e', 'b', 'c', 'd', 'i', 'f', 'g', 'h', 'o', 'j', 'k', 'l', 'm', 'n', 'u', 'p', 'q', 'r', 's', 't', 'a', 'v', 'w', 'x', 'y', 'z']
let arr = ['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd']
let arrSorted = arr.sort() //Natural sorting
console.log(arrSorted)
// output in array
const newArr = arrSorted.sort((a, b) => pattern.indexOf(a[1]) - pattern.indexOf(b[1]))
console.log(newArr) //Sorted by its 2nd character with given pattern
// single output without array
for (let i = 0; i < pattern.length; i++) {
for (let j = 0; j < arrSorted.length; j++) {
if (pattern[i] === arrSorted[j][1]) {
console.log(arrSorted[j]) //Sorted by its 2nd character with given pattern
}
}
}
You could sort the first by string and the second by custom value.
const
pattern = 'ebcdifghojklmnupqrstavwxyz',
array = ['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd'],
order = Object.fromEntries(Array.from(pattern, (l, i) => [l, i + 1]));
array.sort((a, b) =>
a[0].localeCompare(b[0]) ||
order[a[1]] - order[b[1]]
);
console.log(array);

Index characters from an array based on user input

I have an array of the entire alphabet from a to z. I also have an input field. I want to be able to find the index of each character from the input field in the alphabet array but my function doesn't work. I've tried storing the text from the input field into an array, and I've tried using a named function for it as well but neither worked.
<input type="text" id="plaintext" placeholder="Plaintext">
<div id="start"><div id="start_text">Start</div></div>
let plaintext = document.getElementById("plaintext");
let alph = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let startB = document.getElementById("start");
let plainParser = [];
startB.addEventListener('click', () => {
for(let i=0; i < alph.length; i++){
console.log(alph.findIndex( () => plainParser.push(plaintext.value.split(''))));
};
});
A shortcut without needing the array is use the charCode of each character.
a starts at 97
const str = 'abc';
for(let s of str){
console.log(s.charCodeAt(0) - 97);
}
I want to … find the index of each character from the input field in the alphabet array
Then instead of looping from 0 to 25:
for(let i=0; i < alph.length; i++){
you should loop over every character from the input:
for (let c of plaintext.value) {
I want to … find the index of each character from the input field in the alphabet array
You have the character, so find the index:
alph.indexOf(c)
v‘là.
let plaintext = document.getElementById("plaintext");
let alph = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let startB = document.getElementById("start");
startB.addEventListener('click', () => {
for (let c of plaintext.value) {
console.log(alph.indexOf(c));
}
});
Here's a slightly refactored version of what I think you are looking for:
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
const result = document.querySelector(".result");
const plaintext = document.getElementById("plaintext");
const startB = document.querySelector(".start");
startB.addEventListener('click', () => {
const source = plaintext.value;
result.innerText = '';
if (!source) return;
const indices = [];
for (let char of source) {
indices.push(alphabet.indexOf(char));
}
result.innerText = indices.join(', ');
});
<input type="text" id="plaintext" placeholder="Plaintext">
<button class="start">Start</button>
<div class="result" style="font-family: monospace;"></div>

For statement returns unexpected value on last assignment

I'm trying to build a simple "cipher" to assign the letters in a string the value of a reversed alphabet (e.g. a=z b=y, etc..) I built a for statement that seems to work until the last call and instead of giving the reversed value instead gives the original value.
I commented out each line in the for statement and then worked through them one at a time to check their returns. The second to last statement (c = rev.indexOf(c);) give the value of 25, 24, 23 (as expected) so I don't understand why when it looks them up in the "letters" matrix it gives a return of a, b, c instead of z, y, x.
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'x', 'z'];
var rev = letters.reverse();
var stringy = function(n){
ns = n.split("");
for (i = 0; i < n.length; i++){
c = ns[i];
c = rev.indexOf(c);
c = letters[c];
console.log(c);
}
}
stringy("abc");
letters.reverse() doesn't just return the reversed array. It reverses the array in place.
If you check the contents of letters after letters.reverse() you'll see that the order has been reversed.
You can use .slice() to make a copy of the array, which you can then reverse:
var rev = letters.slice().reverse();
As an addition to zzzzBov information to the Array.reverse() method, I thought I would add an answer that doesn't require reversing your letters. There is no need to keep 2 variables just to reverse them based on the index, just find the index in the letters array and search from the end of the letters array back.
I added a slightly modified version of your code, to show how you could make it yourself a bit easier and added some code comments where I thought appropriate
// make your debugging easier
'use strict';
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'x', 'z'];
var getReversedCypher = function( text, sequence, unmatched ) {
if (!text) {
return '';
}
var ns = text.split(''),
cypher = [],
lastLetterIndex = sequence.length - 1;
// use strict adds forEach on arrays
ns.forEach(function(char) {
var index = sequence.indexOf(char);
if (index < 0) {
// couldn't find a match, you could throw an error, I chose to add an extra character
cypher.push( unmatched || '-' );
} else {
// no need to use a reversed lookup, just search the table from the end
cypher.push( sequence[lastLetterIndex-index] );
}
});
return cypher.join('');
};
// make some utility methods to still use your simple function
var encode = function( text ) {
return getReversedCypher( text, letters, '-' );
};
var decode = function( text ) {
return getReversedCypher( text, [].concat(letters).reverse(), ' ' );
};
var encoded = encode("this is the sound of speech"), decoded = decode(encoded);
console.log('cypher: ' + encoded);
console.log('decoded: ' + decoded);

Remove string characters from a string if not matched in an array

I am trying to loop over an array which contains strings that I want my input string to compare with. So approach is I am looping over an input string to check if each character matches with one of the elements present in the array. If not just replace that character with just ''. Note: regular expression is really not an option.
Here is how my JavaScript looks like
var input = 'this is A [{}].-_+~`:; *6^123##$%&*()?{}|\ ';
input.toLowerCase(input)
var allowed = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d', 'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','s','à','â','ä','è','é','ê','ë','î','ï','ô','œ','ù','û','ü','ÿ','ç','À','Â','Ä','È','É','Ê','Ë','Î','Ï','Ô','Œ','Ù','Û','Ü','Ÿ','Ç', ' ']
var cleanStr = '';
for(var i = 0; i < input.length; i++){
for(var j = 0; j< allowed.length; j++){
if(input[i] !== allowed[j]){
cleanStr = input.replace(input[i], ' ');
console.log(cleanStr);
}
}
}
The console log output doesn't appear to be any different than the input field. What am I missing?
Here is my fiddle
https://jsfiddle.net/sghoush1/nvnk7r9j/4/
You can do this in a single loop.
var input = 'this is A [{}].-_+~`:; *6^123##$%&*()?{}|\ ';
input = input.toLowerCase(); // Note the syntax here
var allowed = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'à', 'â', 'ä', 'è', 'é', 'ê', 'ë', 'î', 'ï', 'ô', 'œ', 'ù', 'û', 'ü', 'ÿ', 'ç', 'À', 'Â', 'Ä', 'È', 'É', 'Ê', 'Ë', 'Î', 'Ï', 'Ô', 'Œ', 'Ù', 'Û', 'Ü', 'Ÿ', 'Ç', ' '];
var cleanStr = '';
// Loop over each character in the string
for (var i = 0; i<input.length; i++) {
// Check if the character is allowed or not
if (allowed.indexOf(input[i]) !== -1) {
// Concat the allowed character to result string
cleanStr += input[i];
}
}
console.log(cleanStr);
document.body.innerHTML = cleanStr;
RegEx Approach:
You can create RegEx from a string using the RegExp constructor. To replace non-allowed characters, negated character class RegEx can be used.
var regex = new RegExp('[^' + allowed.join('') + ']', 'g');
var cleanStr = input.replace(regex, '');
Note: You'll need to escape meta-characters that have special meaning in the Character class.
Meta-characters that are needed to escape by preceding backslash \ in the character classQuoting from www.regular-expressions.info.
In most regex flavors, the only special characters or metacharacters inside a character class are the closing bracket (]), the backslash (\), the caret (^), and the hyphen (-).
var input = 'this is A [{}].-_+~`:; *6^123##$%&*()?{}|\ ';
var allowed = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 's', 'à', 'â', 'ä', 'è', 'é', 'ê', 'ë', 'î', 'ï', 'ô', 'œ', 'ù', 'û', 'ü', 'ÿ', 'ç', 'À', 'Â', 'Ä', 'È', 'É', 'Ê', 'Ë', 'Î', 'Ï', 'Ô', 'Œ', 'Ù', 'Û', 'Ü', 'Ÿ', 'Ç', ' '];
var regex = new RegExp('[^' + allowed.join('') + ']', 'gi');
console.log(regex);
var cleanStr = input.replace(regex, '');
console.log(cleanStr);
If the allowed characters array is fixed, you can use following RegEx to replace the non-allowed characters. Also, there is no need to convert the string to lower-case, use i flag for case-insensitive match.
var regex = /[^0-9a-zàâäèéêëîïôœùûüÿç ]/gi;
RegEx101 Live Demo
Using ES6's Set class, available in all good browsers:
let input = 'this is A [{}].-_+~`:; *6^123##$%&*()?{}|\ '.toLowerCase();
let allowed = new Set(['0','1','2','3','4','5','6','7','8','9','a','b','c','d', 'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','s','à','â','ä','è','é','ê','ë','î','ï','ô','œ','ù','û','ü','ÿ','ç','À','Â','Ä','È','É','Ê','Ë','Î','Ï','Ô','Œ','Ù','Û','Ü','Ÿ','Ç', ' ']);
let cleanStr = [].map.call(input, c => allowed.has(c) ? c : ' ').join('');
The last line uses an efficient Set lookup operation to determine if the character is allowed or not.
The [].map.call(input, ...) allows the Array.prototype.map function to operate directly on the input string. Since the result is an array, it needs to be joined back together again afterwards.
In algorithmic complexity terms, this uses two O(n) array operations, and n Set lookups - I don't know what complexity they have but it'll be likely O(log n) or perhaps even O(1), depending on the implementation.
The creation of the initial Set has a computation cost too, of course, but it's trivial and should be done just once, e.g. when the program starts.
If instead you actually wanted to remove the non-matching characters, you could use .filter instead of .map:
let cleanStr = [].filter.call(input, c => allowed.has(c)).join('');
Ok so the problem with your code is that every time you loop to check if an element of the input is allowed, you assign cleanStr to the input with only that character changed to an empty string element. Keep in mind that at every loop your input is always the same and clearStr is the result of the last replacement you did. So you are actually throwing away every replacement done so far and at the end of your computation you will have the input string with only the last replacement you did. What you wanna do is build the resulting string incrementally, so that at the end of the loop you have the result you expected.
var input = 'this is A [{}].-_+~`:; *6^123##$%&*()?{}|\ ';
input.toLowerCase(input)
var allowed = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d', 'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','s','à','â','ä','è','é','ê','ë','î','ï','ô','œ','ù','û','ü','ÿ','ç','À','Â','Ä','È','É','Ê','Ë','Î','Ï','Ô','Œ','Ù','Û','Ü','Ÿ','Ç', ' ']
var cleanStr = '';
for(var i = 0; i < input.length; i++){
if(allowed.indexOf(input[i]) !== -1){
cleanStr += input[i];
}
}
console.log(cleanStr);
I thought it was important for you to understand what was your mistake. Other than the fact that you can use some builtin functions of js to avoid a double for loop for such a simple task. Although as many suggested a regex would be much more efficient.

Print ZZZ to AAA or ZZZ to 000 using Javascript

I need to create a series consisting of combinations of letters and numbers reversing through the alphabet and 9-0 like the following:
ZZZ
ZZY
ZZX
.
.
ZZ9
ZZ8
.
.
ZZ0
ZYZ
ZXZ
.
.
.
AAA
999
.
.
.
000
Following code will print out the series from ZZZ to AAA:
var d1=91, d2=90, d3=90;
while(d1+d2+d3>195){
if(d1>65) d1--;
else if(d2>65){d2--;d1=90;}
else{d3--;d2=d1=90;}
console.log(String.fromCharCode(d3)+String.fromCharCode(d2)+String.fromCharCode(d1));
}
And you can add the following code after to print out the series from 999 to 000:
var d1=10, d2=9, d3=9;
while(d1+d2+d3>0){
if(d1>0) d1--;
else if(d2>0){d2--;d1=9;}
else{d3--;d2=d1=9;}
console.log(d3+''+d2+''+d1);
}
One option, Base36 (you would need to 0..999 as an exception and add padding)
First 100:
var ZZZ = 46655;
for (var i = ZZZ; i > ZZZ - 100; i--)
console.log(i.toString(36).toUpperCase());
you can do it with simple nested loops like this:
var options = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
for(var i=options.length-1; i>=0; i--) {
for(var j=options.length-1; j>=0; j--) {
for(var k=options.length-1; k>=0; k--) {
console.log(options[i] + options[j] + options[k]);
}
}
}
Here is a fiddle.

Categories