この前の質問への回答に基づいてコードを更新した後、次の解決策を思いつきました。
var Coder = (function() {
var controlWords = [
['ONE','OO'],
['TWO','TT'],
['THREE','RR'],
//['...','..'],
['END','NN']
],
map = {
'0':' ', '1':'_', '2':',',
'3':'.', '4':'?', '5':'!',
'6':'\'','7':'"', '8':'(',
'9':')', 'a':'o', 'b':'d',
'c':'a', 'd':'e', 'e':'p',
'f':'i', 'g':'f', 'h':'v',
'i':'u', 'j':'l', 'k':'m',
'l':'y', 'm':'q', 'n':'x',
'o':'b', 'p':'j', 'q':'t',
'r':'n', 's':'z', 't':'w',
'u':'k', 'v':'h', 'w':'s',
'x':'c', 'y':'r', 'z':'g'
},
reverseMap = (function() {
var j, tmp = {};
for (j in map){
if (Object.prototype.hasOwnProperty.call(map, j))
tmp[map[j]] = j;
}
return tmp;
})(),
value, i,
encode = function(data) {
var input = (typeof data == 'string' ? data : '');
console.log('Input to encode: '+input);
for (i = 0; i < controlWords.length; i++) {
value = new RegExp(controlWords[i][0],'g');
input = input.replace(value,controlWords[i][1]);
}
console.log('Encode step 1: '+input);
input = input.replace(/./g, function(c){
return reverseMap[c]
|| reverseMap[c.toLowerCase()].toUpperCase();
});
console.log('Encoding output: '+input);
return {length: input.length, data: input};
},
decode = function(data) {
var input = (typeof data == 'string' ? data : '');
console.log('Input to decode: '+input);
input = input.replace(/./g, function(c){
return map[c]
|| map[c.toLowerCase()].toUpperCase();
});
console.log('Decode step 1: '+input);
for (i = 0; i < controlWords.length; i++) {
value = new RegExp(controlWords[i][1],'g');
input = input.replace(value,controlWords[i][0]);
}
console.log('Decoding output: '+input);
return {length: input.length, data: input};
};
return {encode: encode, decode: decode};
})();
var str = 'ONE Hello, TWO JavaScript THREE World! END',
enc = Coder.encode(str).data,
dec = Coder.decode(enc).data;
ご覧のとおり、完全にまたはほとんど繰り返されるコードがたくさんあります。map
唯一の意味のある違いは、2 つの変換が行われる順序、またはが使用されるかどうかreverseMap
、および各制御語配列のどのインデックスが正規表現として使用され、どのインデックスが置換値として使用されるかです。
繰り返されるコードをサブ関数でラップしてその関数を呼び出すという概念に従うために、次の試みを行いました。2 つの変換を内部関数として定義し、引数の値に基づいてtype
残りを決定します。
var Coder = (function() {
var controlWords = [ /* same */ ],
map = { /* same */ },
reverseMap = /* same */,
code = function(data, type) {
var input = (typeof data == 'string' ? data : ''),
mapping, x, y, value, i,
transform = function() {
return input.replace(/./g, function(c){
return mapping[c]
|| mapping[c.toLowerCase()].toUpperCase();
});
},
replace = function() {
for (i = 0; i < controlWords.length; i++) {
value = new RegExp(controlWords[i][x],'g');
input = input.replace(value,controlWords[i][y]);
}
return input;
};
if (type == 'decode') {
mapping = map;
x = 1;
y = 0;
input = transform();
input = replace();
} else if (type == 'encode') {
mapping = reverseMap;
x = 0;
y = 1;
input = replace();
input = transform();
} else {
throw new Error('Invalid type argument!');
}
return {data: input, length: input.length};
};
return {code: code};
})();
var str = 'ONE Hello, TWO JavaScript THREE World! END',
enc = Coder.code(str, 'encode').data,
dec = Coder.code(enc, 'decode').data;
ただし、このコードは実際にはもっと長いことに気付くかもしれません。「エンコード」と「デコード」よりも多くのタイプを追加したい場合は、さらに簡単に拡張できます(そうするつもりはありません)。しかし、現在は効率が悪いですか?
次に、2 つの関数を使用してバージョンに戻りました (「タイプ」の受け渡しとチェックを避けるため)。
var Coder = (function() {
var controlWords = [ /* same */ ],
map = { /* same */ },
reverseMap = { /* same */ },
input, mapping, x, y, value, i,
transform = function() {
return input.replace(/./g, function(c){
return mapping[c]
|| mapping[c.toLowerCase()].toUpperCase();
});
},
replace = function() {
for (i = 0; i < controlWords.length; i++) {
value = new RegExp(controlWords[i][x],'g');
input = input.replace(value,controlWords[i][y]);
}
return input;
},
encode = function(data) {
input = (typeof data == 'string' ? data : '');
mapping = reverseMap;
x = 0;
y = 1;
input = replace();
input = transform();
return {length: input.length, data: input};
},
decode = function(data) {
input = (typeof data == 'string' ? data : '');
mapping = map;
x = 1;
y = 0;
input = transform();
input = replace();
return {length: input.length, data: input};
};
return {encode: encode, decode: decode};
})();
// Call methods same as first example
コードの長さに実際には役立たず、コードを拡張したり、公開プロジェクトとしてリリースしたりする予定がない場合、コードを繰り返すか、追加の機能/チェックを追加するか、どちらが優れているかを基本的に質問するための長い投稿ですか? これらのうち、最もエレガントなソリューションはどれですか?
編集
mapping
一般的にクリーンアップするために私が考えた 1 つの方法は、 、x
、およびの変数宣言を削除し、それらを引数としてandy
に渡すことです。これはreplace
transform
decode = function(data) {
var input = (typeof data == 'string' ? data : '');
input = transform(map);
input = replace(1,0);
return {length: input.length, data: input};
}