【问题标题】:Get Array of All Possible l33t Combinations in Javascript获取 Javascript 中所有可能的 l33t 组合的数组
【发布时间】:2019-01-17 16:55:53
【问题描述】:

我有一个字符串,我想在使用以下替换时获得所有可能的replace-ment 组合:

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", ...].

顺序并不重要。想法?

【问题讨论】:

    标签: javascript arrays string prototype str-replace


    【解决方案1】:

    我会使用递归方法,逐个字符遍历字符串:

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

    如果你真的在原型上需要它,那也是可能的,但我不建议这样做:

     String.prototype.l33t = function() {
       return [...l33t(this)];
     };
    
     console.log("stuff".l33t());
    

    【讨论】:

      【解决方案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】:

        你可以用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)

        【讨论】:

        • 把它包装在一个原型函数中,它的速度非常快!很好的答案,谢谢!
        【解决方案4】:

        我以递归的方式处理了这个问题,在递归的每次迭代中,都会分析字符串的一个新字符,如果这个字符有替换,那么characterreplacement 都连接到所有以前的结果产生一组新的结果,否则只有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());

        【讨论】:

          【解决方案5】:

          我认为这可能会产生预期的结果!循环遍历每个字母,每次找到新的替换词时,向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());

          【讨论】:

          • 就可读性而言,这是我最喜欢的答案!感谢您的明确回答:)
          • 没问题!它必须使用数组includes 方法这一事实让我感到困扰,并且可能使它比其他方法效率低。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-03-20
          • 2013-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多