Reputation: 1410
Yes, I want a character "translate" function in javascript like that in php. I made the following, but it is ghastly. Surely there must be a better way -- using regular expressions?
<html>
<head>
<script>
window.onload = function() {
"use strict";
console.log(translate("abcdefg", "bdf", "XYZ")); // gives aXcYeZg -=-=-
}
function translate(v1, xlatfrom, xlatto) {
var ch, ipos, retstr = "";
if (xlatfrom.length != xlatto.length) return ""; // lengths must be =
for (var i1=0; i1<v1.length; i1+=1) { // go through string
ch = v1.substring(i1, i1+1); // character by character
ipos = xlatfrom.indexOf(ch); // ck if in xlatfrom
if (ipos >= 0) ch = xlatto.substring(ipos, ipos+1); // if yes, replace
retstr += ch; } // build up return string
return retstr;
}
</script>
</head>
<body>
</body>
</html>
EDIT: I've accepted the @dani-sc answer. I'm not going to pursue performance. But it's so DIDACTIC! And thanks for the "spread operator" info. Here's how I might use his answer:
function translate(v1, xlatfrom, xlatto) { // like the PHP translate
var mapobj = strsToObject(xlatfrom, xlatto); // make str1.ch's:str2ch's object
return [...v1].map(ch => mapobj[ch] || ch).join(''); // ... is js "spread operator"
}
function strsToObject(str1, str2) { // make object from strings
if (str1.length != str2.length) return {}; // lengths must be =
var retobj = {};
for (var i1=0; i1<str1.length; i1+=1) { // just str[i1]: str2[i1]
retobj[str1.substring(i1, i1+1)] = str2.substring(i1, i1+1); }
return retobj;
}
or (this is GREAT! THANKS!)
function translate(v1, xlatfrom, xlatto) { // like the PHP translate
if (xlatfrom.length != xlatto.length) return ""; // lengths must be =
var mapobj = {}; // make object for mapping
for (var i1=0; i1<xlatfrom.length; i1+=1) { // just str[i1]: str2[i1]
mapobj[xlatfrom.substring(i1, i1+1)] = xlatto.substring(i1, i1+1); }
return [...v1].map(ch => mapobj[ch] || ch).join(''); // ... is js "spread operator"
}
Upvotes: 0
Views: 2043
Reputation: 308
Well, if you want, you could use regular expressions like this:
function translate(input, oldCharacters, newCharacters) {
let output = input;
const oldChArr = [...oldCharacters];
const newChArr = [...newCharacters];
for (let i = 0; i < oldChArr.length; i += 1) {
output = output.replace(new RegExp(oldChArr[i], 'g'), newChArr[i]);
}
return output;
}
function translateFixed(input, replacements) {
return input.replace(/./g, ch => replacements[ch] || ch);
}
function translateFixedNoRegEx(input, replacements) {
return [...input].map(ch => replacements[ch] || ch).join('');
}
console.log(translate("abcdefgbdb", "bdf", "XYZ"));
console.log(translate("abcdefg", "cde", "dec"));
console.log(translateFixed("abcdefg", {c: 'd', d: 'e', e: 'c'}));
console.log(translateFixedNoRegEx("abcdefg", {c: 'd', d: 'e', e: 'c'}));
If you would be okay with changing the method's signature, it could be made a bit more concise of course.
Edit: I've added two more methods which actually achieve what you're looking for. Just for reference, I left the original method translate
in there as well.
translateFixed
uses regular expressions to match every single character and replace it if it was specified in the replacements
parameter.
translateFixedNoRegex
just creates an array of characters out of the input
string and iterates over them. If the character ch
matches one in the replacements
parameter, it's replaced, otherwise it's left unchanged. Afterwards, we'll convert it back to a string by concatenating the characters.
You asked about [...array]: It's the spread operator, introduced with ES6. When used on a string, it just takes every character and puts it as a single entry into an array. That means, these both lines are equivalent:
console.log([..."mystring"]);
console.log("mystring".split(''));
Upvotes: 2
Reputation: 22885
function translate(val, xlatfrom, xlatto) { //
if (xlatfrom.length !== xlatto.length) return "";
Array.from(xlatfrom).forEach((key, index) => {
val = val.replace(key, xlatto[index]);
})
return val;
}
console.log(translate("abcdefg", "bdf", "XYZ"));
Upvotes: -1