Get Array of All Possible Replacement Combinations in Javascript?

问题: I have a string that I'd like to get all possible replace-ment combinations on using the following substitutions: var equiv = { "a": "4", "b": "8", "e": "3", "i":...

问题:

I have a string that I'd like to get all possible replace-ment combinations on using the following substitutions:

var equiv = {
  "a": "4",
  "b": "8",
  "e": "3",
  "i": "1",
  "l": "1",
  "o": "0",
  "t": "7"
}

I would like to define a String.prototype function, something like:

String.prototype.l33tCombonations = function()
{
    var toReturn = [];

    for (var i in equiv)
    {
        // this.???
        // toReturn.push(this???)
    }

    return toReturn;
}

So I could feed in something like "tomato".l33tCombinations() and get back:

["tomato", "t0mato", "t0mat0", "tomat0", "toma7o", "t0ma7o", "t0m470", ...].

Order is not important. Thoughts?


回答1:

I would use a recursive approach, that traverses the string char by 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"));

If you really need it on the prototype thats also possibl3, but I wouldn't recommend that:

 String.prototype.l33t = function() {
   return [...l33t(this)];
 };

 console.log("stuff".l33t());

回答2:

You could take a cartesian product for generating the wanted values.

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:

You can do something like this using reduce

The idea is to loop through each character and add every combination to the accumulator. If you encounter a character which isn't part of equiv, just add the character to every item in the accumulator. If the character does exist in equiv, duplicate all the previous combinations and add another set of combinations with the 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)


回答4:

I have approached this in a recursive way, on each iteration of the recursion, a new character of the string is analyzed, if this character have a replacement, then both the character and the replacement are concatenated to all previous results making a new set of results, otherwise only the character is concatenated to all the previous results. Note, I have abuse of the spread operator for this approach.

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());


回答5:

I think this might yield the desired result! Loop through each letter and every time a new replacement is found, add a new word to toReturn and make sure to search each new word!

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());

  • 发表于 2019-01-18 22:17
  • 阅读 ( 231 )
  • 分类:网络文章

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除