dcromley
dcromley

Reputation: 1410

A "translate" function in javascript like that in php?

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

Answers (2)

dani-sc
dani-sc

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

Zohaib Ijaz
Zohaib Ijaz

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

Related Questions