使用javascript检查字符串是否是数组中字符串的组合

时间:2017-05-30 12:35:13

标签: javascript arrays string algorithm

我需要检查字符串是否由数组中给出的任何字符串组合形成 例如:我们有一些[" for"," car"," keys"," forth"]和一串&#34 ;如果字符串是" forthcarxykeys",则结果应为false,因为xy不在数组中。数组中的单词顺序无关紧要。  没有必要匹配数组中的所有字符串,但测试字符串应该只由数组中的任何字符串组成。如果它包含除数组中的字符串以外的任何字符串,则返回false

我的方法:

var str = "forthcarkeys";
var arr = ["for","car","keys","forth"];
for(var i=0;i<arr.length;i++)
{
   if(str.indexOf(arr[i]) !== -1)
   {
      str.replace(arr[i],"");
   }
}

if(str !== "")
{
  console.log("yes");
} else 
{
  console.log("no");
}

但这种方法效率低下且失败。

7 个答案:

答案 0 :(得分:2)

一种可能的方法是检查每个前缀是否可以使用输入字符串表示。

我们的想法是,如果我们可以轻松计算长度为 i 的前缀是否可以用输入字符串表示,如果我们已经有这些信息用于更短的前缀(这可以通过检查是否任何允许的字符串都会导致更短的可表达前缀) - 请参阅下面的代码。

&#13;
&#13;
var str = "forthcarkeys";
var arr = ["for","car","keys","forth"];

// isPossible[i] indicates whether we can express the 
// prefix str.substring(0, i) using strings in arr.
var isPossible = Array(str.length + 1).fill(false);

// it is always possible to construct the empty string
isPossible[0] = true;

// consider each prefix of str, from shortest to longest
for (var i = 1; i <= str.length; i++) {
  // try to reach this prefix using an allowed string s_allowed,
  // by appending s_allowed to a shorter prefix
  for (var j = 0; j < arr.length; j++) {
    // "start" is the position where the current string 
    // would need to be appended
    start = i - arr[j].length;

    if (start >= 0 && isPossible[start]) {
      if (str.substring(start, i) == arr[j]) {
        isPossible[i] = true;
        // we break the loop over j, because we already found a
        // solution to express the current prefix str.substring(0,i)
        break;
      }
    }
  }
}

for (var i = 1; i <= str.length; i++) {
  console.log(str.substring(0, i) + " - " + isPossible[i] + "\n")
}

if (isPossible[str.length]) {
  console.log("yes");
} else {
  console.log("no");
}
&#13;
&#13;
&#13;

要进一步详细说明其工作原理,请考虑一个较小的示例:

  • str =&#34; abcd&#34;
  • arr = [&#34; ab&#34;,&#34; a&#34;,&#34; cd&#34;]

此处描述的方法按照其长度的递增顺序测试str的所有前缀:

步骤0:空前缀 - 这被认为总是很好(可以使用0个字符串表示)。

第1步:前缀&#34; a&#34;:

我们尝试使用较短的前缀+一个允许的字符串来获取此前缀。为此,我们遍历允许的字符串:

  • &#34; AB&#34;不能附加到较短的前缀,以获得&#34; a&#34; (因为起始位置需要为-1)。
  • &#34;&#34;可以附加到空前缀,这总是很好 - 因此我们得到前缀&#34; a&#34;很好(可以用允许的字符串表示)。

第2步:前缀&#34; ab&#34;:

我们尝试使用较短的前缀+一个允许的字符串来获取此前缀。为此,我们遍历允许的字符串:

  • &#34; AB&#34;可以附加到空前缀,这总是很好 - 因此我们得到前缀&#34; ab&#34;很好(可以用允许的字符串表示)。

第3步:前缀&#34; abc&#34;:

我们尝试使用较短的前缀+一个允许的字符串来获取此前缀。为此,我们遍历允许的字符串:

  • &#34; AB&#34; - 将这个附加到较短的前缀并获得当前的&#34; abc&#34;前缀,我们需要从位置1开始,但是从该起始位置起的子串是&#34; bc&#34;,因此我们不能追加字符串&#34; ab&#34;得到前缀&#34; abc&#34;。
  • &#34;&#34; - 与上述类似,我们无法追加&#34; a&#34;得到前缀&#34; abc&#34;。
  • &#34; CD&#34; - 与上面类似,我们不能追加&#34; cd&#34;得到前缀&#34; abc&#34;。

我们耗尽了所有允许的字符串,因此前缀&#34; abc&#34;无法表达使用允许的字符串。

第4步:前缀&#34; abcd&#34; (整个字符串):

我们尝试使用较短的前缀+一个允许的字符串来获取此前缀。为此,我们遍历允许的字符串:

  • &#34; AB&#34; - 将此附加到较短的前缀并获得当前的#ab;&#34;前缀,我们需要从位置2开始,但是来自该起始位置的子串是&#34; cd&#34;,因此我们不能追加字符串&#34; ab&#34;得到前缀&#34; abcd&#34;。
  • &#34;&#34; - 与上述类似,我们无法追加&#34; a&#34;得到前缀&#34; abcd&#34;。
  • &#34; CD&#34; - 我们可以将这个允许的字符串附加到&#34; ab&#34;字首。在上一步中,我们发现&#34; ab&#34;前缀很好(可以用给定的字符串表示),因此很好来追加&#34; cd&#34;从那里。

因此,我们得到前缀&#34; abcd&#34; (对应于整个字符串)可以使用输入字符串表示。

答案 1 :(得分:0)

如果sort的条件为Dec,则需要yes数组str==""订单

function check(str){
var arr = ["for", "car", "keys", "forth"];
arr= arr.sort((a,b)=> b.length-a.length) // sort with length dec order
console.log(arr) //longest length string is first then to lower length
for (var i = 0; i < arr.length; i++) {
    str = str.replace(arr[i], ""); 
}

if (str.trim()== "") { //empty 
  console.log("yes");
} else {
  console.log("no");
}
}

check("forthcarkeys")
check("forthcarxykeys")

答案 2 :(得分:0)

如果首先匹配所有单词,则可以在开始时省略不出现的单词。然后,如果匹配是在字符串中出现的顺序,则可以使用递归来查找匹配后的所有匹配项:

&#13;
&#13;
function eval(str, wordList = ["for","car","keys","forth", "the"]){	//note, added 'the' for testing
	if(!str)return false; //empty string -> false
  
  const words = wordList.map(w=> ({word:w, index: str.indexOf(w)})) //map all words with their occurence index inside the string
  	.filter(w=>w.index !== -1) //get rid of non occuring words alltogether
  	.sort((w1,w2) => w1.index - w2.index); //sort by index of occurence
  
  const check = (arr,ind) => {
  	if(ind>=str.length)return ind === str.length; //end of string reached -> match if exactly at end (false if greater than)
  	let w;    
    while(arr.length){
  	 	[w,...arr] = arr; //destructure: w = next word (index 0), arr is set to the remaining elements
      if(w.index > ind) return false; //gap since last match -> no match
      if(w.index===ind && check(arr,ind + w.word.length)) //if match is at the expected index, check the next indices
      	return true; //word started at the 'current' index and remaining words match as well   	
      //if code arrives here, try further with next word (while)
		}
    return false;
  };
  return check(words,0); //start recursive function with all words at string index 0
}

//test
function test(str, words){
	console.log(str,':', eval(str, words));
}
test("forthcarkeys");
test("forthcarxykeys");
test("forthecar");
test("abcdef",[ "abc", "def", "abcd" ]);
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您可以进行扩展尝试并搜索每个单词,并使用临时结果集过滤掉单词是否在字符串中。

function check(string, array) {

    function fork(i, t) {
        var s = t.slice(), j;
        if (i === possibilities.length) {
            result.push(t.join(''));
            return;
        }
        if (possibilities[i].word.split('').every(function (c, j) { return s[j + possibilities[i].position] !== ''; })) {
            for (j = 0; j < possibilities[i].word.length; j++) {
                s[j + possibilities[i].position] = ''
            }
        }
        fork(i + 1, s);
        fork(i + 1, t);
    }

    var possibilities = array.reduce(function (r, a) {
            var p = string.indexOf(a);
            while (p !== -1) {
                r.push({ word: a, position: p });
                p = string.indexOf(a, p + 1);
            }
            return r;
        }, []),
        result = [];

    console.log(possibilities);
    fork(0, string.split(''));
    console.log(result);
    return result.some(function (a) { return !a; });
}

console.log(check("forthcarkeyboardingfor", ["for", "car", "key", "forth", "keyboard", "boarding"]));    // true
console.log(check("forthxycarkeyboardingfor", ["for", "car", "key", "forth", "keyboard", "boarding"]));  // false
.as-console-wrapper { max-height: 100% !important; top: 0; }

上述版本,提前退出。

function check(string, array) {

    function fork(i, t) {
        var s = t.slice(), j;
        if (i === possibilities.length) {
            return !t.join('');
        }
        if (possibilities[i].word.split('').every(function (c, j) { return s[j + possibilities[i].position] !== ''; })) {
            for (j = 0; j < possibilities[i].word.length; j++) {
                s[j + possibilities[i].position] = '';
            }
        }
        return fork(i + 1, s) || fork(i + 1, t);
    }

    var possibilities = array.reduce(function (r, a) {
            var p = string.indexOf(a);
            while (p !== -1) {
                r.push({ word: a, position: p });
                p = string.indexOf(a, p + 1);
            }
            return r;
        }, []);

    return fork(0, string.split(''));
}

console.log(check("forthcarkeyboardingfor", ["for", "car", "key", "forth", "keyboard", "boarding"]));    // true
console.log(check("forthxycarkeyboardingfor", ["for", "car", "key", "forth", "keyboard", "boarding"]));  // false

答案 4 :(得分:0)

这是一个更强大的函数,可以找到用于组成它的所有可能元素和方法。如果结果的长度为零,则无法从池中生成原始文本。

function decompose(orignal, pool) {  // recurisve function to find combinations of text
  var results = [];
  for (var element of pool) {     // for each element in pool
    if (orignal == element) {     // resursive base case, stop when orignal == element
      results.push([element]);    // * add solution
    } else {
      if (orignal.indexOf(element) == 0) {                    // if original text starts with element
        var remaining = orignal.slice(element.length);        // ready remaining text to be scanned
        var subresults = decompose(remaining, pool); // recursive call: findCombinationsOf remaining
        for (subresult of subresults) {
          results.push([element].concat(subresult));          // * add solution
        }
      }
    }
  }
  return results;
}

console.log(JSON.stringify(decompose("forthcarkeys", ["for","car","keys","forth"])));
console.log(JSON.stringify(decompose("forthcarkeys", ["for","car","keys","forth", "th"])));
console.log(JSON.stringify(decompose("nowaydude!", ["for","car","keys","forth", "th"])));

答案 5 :(得分:0)

这是我的解决方案

详细说明:

  1. 将给定字符串"forthcarxykeys"转换为数组并将其分配给变量chars
  2. 遍历给定的数组["for","car","keys","forth"]
  3. 每次迭代,检查数组中是否存在单词(即"for"
  4. 如果存在,请获取找到的每个字母的索引,并在true数组中将其标记为char
  5. 如果chars中的所有值都为true,则返回true,否则返回false。
  6. JS:

    // arr = ["for", "car", "keys", "forth"];
    // str = "forthcarxykeys";
    
    function check(arr, str) {
        let chars = str.split('');
        for (let i = 0; i < arr.length; i++) {
            let word = arr[i];
            let index = str.indexOf(word);
            let wordExists = index !== -1;
            if (wordExists) {
                let endIndex = index + word.length;
                for (index; index < endIndex; index++) {
                    chars[index] = true;
                }
            }
        }
        return chars.every(i => i === true);
    }
    

答案 6 :(得分:-1)

这是更新的代码。字符串替换不起作用,因此使用正则表达式来实现这一点。 var re = new RegExp(arr[i], 'g');

&#13;
&#13;
function check(str, arr) {
  var flag = true;
  for (var i = 0; i < arr.length; i++) {
    if (str.indexOf(arr[i]) === -1) {
      flag = false;
    }
  }

  if (!flag) {
    console.log("Some keys didn't matched.");
  } else {
    console.log("Nothing remains. All matched.");
  }
}

var str = "forcarxy";
var arr = ["for", "car", "keys", "forth"];
check(str, arr);
var arr = ["abcd", "def", "abc"];
var str = "abcdef";
check(str, arr);
var arr = [ "abcd", "cdef" ];
var str = "abcdef";
check(str, arr);
var str = "aabc";
var arr = ["a", "bc"];
check(str, arr);
&#13;
&#13;
&#13;

代码已更新,以考虑@inetphantom

的评论案例