如何调整此Javascript代码以打印每行输入的所有句子排列?

时间:2017-07-10 14:44:05

标签: javascript string loops

例如,如果我有这个输入:

I am the man

我想回去:

I am the man
I the man
I man
I the
I am
am the man
am man
am the
the man
man
man I
man I am
etc.

这是我到目前为止输入的前20个句子

            for (var i = 0; i < 20; i++) {
                var currWords = data[i].DisplayName.replace(/[^\x00-\x7F]/g, "").replace(/\(/g, "").replace(/\-/g, " ").replace(/\)/g, "").replace(/\*/g, "").toLowerCase().split(/\s+/g);

                for (var j = 0; j < currWords.length; j++) {
                    var currString = "";
                    for (var k = j; k < currWords.length; k++) {
                        currString += (currWords[k] + " ");
                    }
                    console.log(currString);
                }
            }

我只是想要这些印刷品,所以我可以复制它们用于别的东西。到目前为止,它只是做前进的事情,我不能想到一个简单的方法,使它做每一个可能的句子。你有什么建议?

2 个答案:

答案 0 :(得分:1)

嗯,关于创建排列的问题,也可以是一般性问题,而不是特定于javascript或句子特定的,可以有多种方法,让我们解释其中一个我现在能想到的短期内容:

那么,你的句子“我就是男人”有四个单词,先将它们分成一个数组,如

var words = "I am the man".split(" ")

所以你的数组的单词["I", "am", "the", "man"]length4,因为你有4个单词。 现在,如何产生这些数字的排列(1234)并使用每个结果的每个数字作为单词数组和连接的索引?困惑?让我解释一下。

如果我们可以生成类似

的数组怎么办?

[1, 2, 3, 4, 12, 13, 14, 21, 23, 24, 41, 42, 43, 123, 124, ...., 4321]

然后从每个数字中你可以构造一个句子:

例如:

1: "I"
4: "man"
43: "man the"
..
..
4321: "man the am I"

(如果你对如何从数字中生成这个字符串有疑问,我会在后面澄清,现在不要忘记你已经有了一系列的单词)

现在,如果我们计算更多9条目的排列,问题可能会发生?对于9,最大值将是987654321(因为我们认为所有内容都是数字),所以在所有情况下我更喜欢构造数组而不是数字,因为最终我们需要拆分所有数字并从word数组索引中获取

所以,而不是

[1, 2, 3, 4, 12, 13, 14, 21, 23, 24, 41, 42, 43, 123, 124, ...., 4321]

我更喜欢

[ [1], [2], [3], [4], [1, 2], [1, 3],..., [3, 4, 1],........., [4, 3, 2, 1] ]

因为数字可以超出9,我们可以轻松处理。

所以,现在的问题是你将如何构建数组(相信我,这是最终的事情,你的输出只是一个逻辑映射)

因此,如果我们通过将数组初始化为:[[1], [2], [3], [4]]达到数组来开始,那么我们将从第2级开始,

我们将循环,1到长度(即1到4),并且在每次迭代中我们将迭代到每个数组并将检查数组是否包含当前数字,否则我们将切片数组,并推送开头的当前数字,然后将其推回主结果数组。我们也将传递每个数字数组,这样我们就不需要查看整个数组,对于第1级,两者都是相同的,所以我们将slice()复制它,我们将返回一个数组也用于当前数字

function processEachDigit(length, mainArray, lastDigitArray) {
    var currDigitArray = [];
    var n;
    for (n = 1; n <= length; n++) {
        for (idx = 0; idx < lastDigitArray.length; idx++) {
            var eachArray = lastDigitArray[idx];
            if (!eachArray.includes(n)) {
                var newArr = eachArray.slice();
                newArr.unshift(n)
                mainArray.push(newArr);
                currDigitArray.push(newArr)
            }
        }
    }
return currDigitArray;
}

所以我们第一次有

mainArray = [[1], [2], [3], [4]] //will initialize through a loop

currDigitArray  = mainArray.slice()
//as we will keep update mainArray we cannot use the same reference

我们称之为

processEachDigit(words.length, mainArray, currDigitArray)

所以mainArray是

[[1], [2], [3], [4]]

它变成了

[[1], [2], [3], [4], [1, 2], [1,3], ......., [4,2], [4,3]]

并返回第二个数字元素的数组,即

[[1,2], [1, 3], [1, 4], [2, 1], [2, 3]......., [4,2], [4,3]]

所以我们将调用第二位数组来构造第3位数组,然后传递第3位数组来构造第4位数组。

现在,我们真的需要最初构建单个数字数组吗? NO。

传递一个空数组的数组会创建它,因为那里找不到任何元素,所以我们都设置只需要将主数组初始化为空数组,将当前数字数组初始化为空数组数组,我只是告诉{{ 1}}以及所有解释我们想要做的事情。

我们走了

slice()

现在您可以使用任意数字调用function getPermutationArray(L) { var mainArr = []; var n; var currDigitArr = [[]]; for(n=1;n<=L;n++) { currDigitArr = processEachDigit(L, mainArr, currDigitArr); } return mainArr; } ,这将返回数组,现在尝试从该数组进行映射。如果你失败了,我会帮助你,这是一件容易的事。

注意: 我本来可以编写一个小代码段,但只写了很多东西来正确解释它,而且可能有很多方法,只是试过其中一个作为我不想去递归,使用递归也可以实现这一点。如果有任何不明确的评论。

快乐编码:)

答案 1 :(得分:1)

After a look at your Question i think you can adapt Heap´s algorithm

i write and adapt this to es6 with the only change, that i build the string with bitCheck operators...

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>I am the man</title>
</head>
<body>
  <div id="output"></div>
  <script>
    p = m => {
      var a = m.split(' '),
      s = new Set(), l = a.length, ms, 
      b = (n=l) => {
        if (n == 1) {
          for ( let i = 1; i < 2**l; i++){
            ms = '';
            for ( let y = 0; y < l; y++){
              if (i & (1 << y)){
                ms += a[y]+" ";
              }
            }
          s.add(ms.trim());
          }
      } 
        else {
          for (let i=0;i<n;i++) {
            b(n - 1);
            [a[(n%2)*i],a[n-1]] = [a[n-1],a[(n%2)*i]];
          }
        }
      }
      b();
      return s;
    }
    test = p("I am the man")
    test.forEach(e => output.innerHTML += e + '<br>');
  </script>
</body>
</html>