HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Substituting Hebrew letter variants

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lettervariantshebrewsubstituting

Problem

I have two functions that replace letters. In one function, I'm replacing a regular Hebrew letter with its final form, and the other function undoes this operation. (Consider it like lowercase/uppercase, except only a few letters have both forms.)

I created an object where the keys are the regular forms and the values are the final forms. In each function, I iterate over the object and run a regex - in one function it's map[i] -> i; the other is i -> map[i].

Would it be worth it / even possible to abstract this for loop into a function?

var map = {
    כ: 'ך',
    מ: 'ם',
    נ: 'ן',
    פ: 'ף',
    צ: 'ץ'
};

exports.toFinal = function(text) {
    for (var i in map) {
        text = text.replace(new RegExp(i,'g'), map[i]);
    }
    return text;
}

exports.toRegular = function(text) {
    for (var i in map) {
        text = text.replace(new RegExp(map[i],'g'), i);
    }
    return text;
}


(exports is Node.js's exports object, and the code is implicitly running in a closure.)

Solution

I would opt for another implementation.

You iterate over your map and for each value, you replace a character in the source string. So for n characters in your map, you run n replacement operations for a length of m. Given, that n = m, that takes n^2 steps.

I would make two maps; one for each direction:
(for simplicity reasons, I chose latin letters)

var form1 = {
    'a':'A',
    'b':'B'
};

var form2 = {
    'A':'a',
    'B':'b'
};


If I need to know, whether there is a translation, I could do a simple operation form1['a'] or form1['x'].

A translation - independent of the direction - could be defined as:

function translate(x){
  return (map[x])?map[x]:x;
}


Is a letter in the map, translate it, else return the original letter.

To specify the direction, you could define a closure, passing in the appropriate map:

function makeTranslation(map){
    return function translate(x){
        return (map[x])?map[x]:x;
    }
}


If you want to translate more than one character, you have to split the string and translate each character. After that join the result:

function translate(expression, direction){
    return expression.split("").map(direction).join("");
}


Which results in two functions:

function toFinal(expression){
    return translate(expression, makeTranslation(form1));
}

function toRegular(expression){
    return translate(expression, makeTranslation(form2));
}


The resulting code looks like this:

var form1 = {
'a':'A',
'b':'B'
};

var form2 = {
'A':'a',
'B':'b'
};

function makeTranslation(map){
return function translate(x){
return (map[x])?map[x]:x;
}
}

function translate(expression, direction){
return expression.split("").map(direction).join("");
}

function toFinal(expression){
return translate(expression, makeTranslation(form1));
}

function toRegular(expression){
return translate(expression, makeTranslation(form2));
}

console.log(toRegular(toFinal("aabbcbb"))==='aabbcbb');
console.log(toFinal(toRegular("AABBcBB"))==='AABBcBB');

Code Snippets

var form1 = {
    'a':'A',
    'b':'B'
};

var form2 = {
    'A':'a',
    'B':'b'
};
function translate(x){
  return (map[x])?map[x]:x;
}
function makeTranslation(map){
    return function translate(x){
        return (map[x])?map[x]:x;
    }
}
function translate(expression, direction){
    return expression.split("").map(direction).join("");
}
function toFinal(expression){
    return translate(expression, makeTranslation(form1));
}

function toRegular(expression){
    return translate(expression, makeTranslation(form2));
}

Context

StackExchange Code Review Q#70606, answer score: 3

Revisions (0)

No revisions yet.