我有一个字符串,希望在使用以下替换项时获得所有可能的replace
组合:
var equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
我想定义一个String.prototype
函数,例如:
String.prototype.l33tCombonations = function()
{
var toReturn = [];
for (var i in equiv)
{
// this.???
// toReturn.push(this???)
}
return toReturn;
}
所以我可以输入类似"tomato".l33tCombinations()
的东西并返回:
["tomato", "t0mato", "t0mat0", "tomat0", "toma7o", "t0ma7o", "t0m470", ...].
顺序并不重要。有想法吗?
答案 0 :(得分:3)
我将使用一种递归方法,逐个遍历字符串char:
const toL33t = { "a": "4", "b": "8", "e": "3", "i": "1", "l": "1", "o": "0", "t": "7" };
function* l33t(string, previous = "") {
const char = string[0];
// Base case: no chars left, yield previous combinations
if(!char) {
yield previous;
return;
}
// Recursive case: Char does not get l33t3d
yield* l33t(string.slice(1), previous + char);
// Recursive case: Char gets l33t3d
if(toL33t[char])
yield* l33t(string.slice(1), previous + toL33t[char]);
}
console.log(...l33t("tomato"));
如果您确实还在原型possibl3上使用它,但我不建议这样做:
String.prototype.l33t = function() {
return [...l33t(this)];
};
console.log("stuff".l33t());
答案 1 :(得分:2)
您可以使用reduce
这个想法是循环遍历每个字符并将每个组合添加到累加器中。如果遇到equiv
中不是 部分的字符,只需将该字符添加到累加器中的每个项目中即可。如果equiv
中存在字符 ,请复制所有先前的组合,并使用equiv[<character>]
const equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
const input = "tomato";
const output = [...input].reduce((acc, c, i) => {
const r = equiv[c];
if (i === 0) {
return r ? [c, r] : [c];
}
const updated = acc.map(a => a + c);
const newItems = r ? acc.map(a => a + r) : [];
return [...updated, ...newItems]
}, [])
console.log(output)
答案 2 :(得分:2)
您可以采用笛卡尔积来生成所需值。
function leet(string) {
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
code = { a: "4", b: "8", e: "3", i: "1", l: "1", o: "0", t: "7" };
return Array
.from(string, c => c in code ? [c, code[c]] : [c])
.reduce(cartesian)
.map(a => a.join(''));
}
console.log(leet('tomatoe'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:2)
我已经以递归的方式解决了这个问题,在每次递归的迭代中,都会分析字符串的一个新字符,如果该字符有一个替换,那么character
和replacement
被连接到所有先前的结果,从而产生一组新的结果,否则,仅将character
连接到所有先前的结果。请注意,我滥用了这种传播工具。
var equiv = {a: "4", b: "8", e: "3", i: "1", l: "1", o: "0", t: "7"};
const genComb = (str, arr) =>
{
if (!str) return arr; // Finish condition.
let c = str[0]; // New char to be appended.
let r = equiv[c]; // New char replacement.
return genComb(
str.slice(1),
[...arr.map(e => e + c), ...(r ? arr.map(e => e + r) : [])]
);
};
String.prototype.l33tCombinations = function()
{
return genComb(this, [""], 0);
}
console.log("tomato".l33tCombinations());
答案 4 :(得分:1)
我认为这可能会产生预期的结果!遍历每个字母,每次找到新的替换字母时,都向toReturn
添加一个新单词,并确保搜索每个新单词!
var equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
String.prototype.l33tCombinations = function() {
var toReturn = [this.toLowerCase()];
for (let i = 0; i < toReturn.length; i++) {
for (let j = 0; j < toReturn[i].length; j++) {
if (equiv[toReturn[i][j]]) {
let newWord = toReturn[i].split('');
newWord[j] = equiv[newWord[j]];
let newWordJoined = newWord.join('');
if (!toReturn.includes(newWordJoined))
toReturn.push(newWordJoined);
}
}
}
return toReturn;
}
console.log('tomato'.l33tCombinations());