如何从字符串中收集所有可能的连续单词序列

How to collect all possible contiguous sequences of words from a string?

本文关键字:有可能 连续 单词序 字符串      更新时间:2023-09-26

例如,如果空格是分隔符和

var str = "ab cde fgh ij klmn opq";

我想要

var result = [
["ab", "cde", "fgh", "ij", "klmn", "opq"],
["ab", "cde", "fgh", "ij", "klmn opq"],
["ab", "cde", "fgh", "ij klmn opq"],
//...
["ab", "cde", "fgh ij", "klmn opq"],
["ab", "cde", "fgh ij klmn", "opq"],
//...
["ab cde", "fgh", "ij", "klmn", "opq"],
["ab cde", "fgh", "ij", "klmn opq"],
//...
["ab cde", "fgh ij", "klmn opq"],
["ab cde", "fgh ij klmn", "opq"],
//...
["ab cde fgh ij klmn", "opq"]
];

解决这样一个问题的有效方法是什么?

我自己的尝试只解决了部分问题:

  1. 删除"ab",然后获取"ab" + ["cde", "fgh", "ij", "klmn", "opq"], ["cde", "fgh", "ij", "klmn opq"]
  2. 删除"ab cde",然后获取"ab cde" + ["fgh", "ij", "klmn", "opq"], ["fgh", "ij", "klmn opq"]

等等。但是这种方法将不允许收集所有可能的序列(如上面的例子所示)。

您可以递归地构建序列。只需将第一个单词连接到从rest构建的每个序列中,或者将其附加为新单词。尽管此解决方案的调用堆栈溢出有一些问题。

但你们可以看到基本的想法。

const str = 'ab cde fgh ij';
function getAllSequences(words) {
  if (words.length === 1) {
    return [words];
  }
  
  const [first, ...rest] = words;
  const sequences = getAllSequences(rest);
  
  return sequences.reduce((sequences, sequence) => {
    const withFirstConnected = [].concat(first + ' ' + sequence[0], sequence.slice(1));
    const withFirstUnshift = [].concat(first, sequence);
    
    return sequences.concat([withFirstConnected], [withFirstUnshift]);
  }, []);
}
console.log(getAllSequences(str.split(' ')));

另一个没有递归的版本,类似的方法,但添加了最后一个单词而不是第一个单词。

function getAllSequences(words) {
  return words.reduce(addWordToSequences, [[]]);
}
function addWordToSequences(sequences, word) {
  return sequences.reduce((sequences, sequence) => {
    if (sequence.length === 0) {
      return [[word]];
    }
    
    const last = sequence[sequence.length - 1];
    const front = sequence.slice(0, sequence.length - 1);
    const withWordJoined = front.concat(last + ' ' + word);
    return sequences.concat([withWordJoined], [sequence.concat(word)]);
  }, []);
}
console.log(getAllSequences('something mdd ala ba'.split(' ')))

您可以使用问题的抽象,尝试只分配所有项的总和,并使用for循环来重新分配已经分配的部分。

function combine(array) {
    function c(l, r) {
        var i, p = 0;
        if (l === 0) {
            result.push(r.map(function (a) {
                p += a;
                return array.slice(p - a, p);
            }));
            return;
        }
        for (i = 1; i <= l; i++) {
            c(l - i, r.concat(i));
        }
    }
    var result = [];
    c(array.length, []);
    return result;
}
console.log(combine("ab cde fgh ij klmn opq".split(' ')));

首先需要获得一组单词,如下所示:

var setOfWords = str.split(" ");

然后,你需要得到你需要的所有组合,比如:

function generateCombinations(setOfWords) {
    var lastIndex = setOfWords.length - 1;
    var firstIndex = setOfWords.length - 1;
    while (lastIndex >= 0) {
        while (firstIndex >= 0) {
            var combination = [];
            for (var index = firstIndex; index <= lastIndex; index++) {
                combination.push(setOfWords);
            }
            var result = combination.join(" ");
            //Do something with result, as it is a valid output
            firstIndex--;
        }
        lastIndex--;
    }
}

如果你试着把连续字符串的数组想象成连续数字的数组,你会很容易理解:

把你的连续字符串数组想象成等价于这个

[ab, cde, fgh, ij, klmn, opq] = [1, 2, 3, 4, 5, 6]

假设这样就可以很容易地解决我们的问题。

初始序列:[1,2,3,4,5,6]-序列-1

现在,您需要理解,这里只有当您连接它们的下一个(字符串或数字)或它们的组合时,才会形成continue。

示例:在初始序列中,5可以与6一起使用,因为6是5旁边的立即数(连续数),但4不能与6一起获得,类似地,4可以与组合56一起使用(连续组合)。我们所需要做的就是,确保这些组合是连续的,并且立即达到4。

首先,我们要做的是使几个连续序列形成初始序列,每个输出序列都是到达另一个连续序列的输入。

示例:

通过插入其紧邻的下一个而获得的序列。

[1,2,3,4,56]  -  Seq  - 2
[1,2,3,45,6]  -  Seq  - 3
[1,2,34,5,6]  -  Seq  - 4
[1,23,4,5,6]  -  Seq  - 5
[12,3,4,5,6]  -  Seq  - 6

同样,我们需要对seq-2到seq-6进行评估。

示例:

Seq-2将导致:

Input->   
 [1,2,3,4,56]  -  Seq  - 2
Sequence obtained by concating their immediate next ones. 
Output->
    [1,2,3,4,56]  -  Seq  - 7
    [1,2,3,456]  -  Seq  - 8
    [1,2,34,56]  -  Seq  - 9
    [1,23,4,56]  -  Seq  - 10
    [12,3,4,56]  -  Seq  - 11

现在,seq-7到seq-11再次是一组新的输入序列,就像序列seq2-seq6一样,并且需要对所有这些序列进行相同的控制。

现在,根据我的说法,有两种可能的方法来实现这一点:1.递归2.堆叠

虽然我不打算为您编写代码,但我将向您简要介绍第二种方法。

Step:1. Initailly your stack in empty.
Step:2  With each input sequence you will obtain some output sequences.
Step:3  Push these output sequences back in the stack.
Step:4  Pop the top of the stack and store it in an temp array and push the outputs back to the stack.
Step:5 Temp array will store all the sequences.

通常,您需要提供一些条件检查,以避免两次推送重复序列。我希望这是有道理的。

此外,我建议你添加算法标签,我会给你更好的答案。与其说是javascript问题,不如说是一个算法问题。