简体   繁体   English

正则表达式:如何计算给定字符串中一个或多个单词的排列?

[英]REGEX: How to count the permutations of a word or words in a given string?

Is there a way to use regex to count the permutations of a word or words in a given string?有没有办法使用正则表达式来计算给定字符串中一个或多个单词的排列? Let's take "NEOTWONE" as our examples which should return a count of "4"让我们以“NEOTWONE”作为我们的示例,它应该返回“4”的计数

  NEO --> 'ONE' --> +1
  OTW --> 'TWO' --> +1
  TWO --> 'TWO' --> +1
  ONE --> 'ONE' --> +1

This is what I have so far and I couldn't get the regex to work properly.这是我到目前为止所拥有的,我无法让正则表达式正常工作。

const nums = ['ZERO','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE'];

function amount(str,count=0) {
  for (const n of nums) {
    RegExp(`\\b[${str}]+\\b`,'g').test(n) && count++;
  }
  return count;
}

console.log(amount('ONE')); // 1
console.log(amount('ONEOTW')); // 2
console.log(amount('ONENO')); // 1
console.log(amount('NEOTWONE')); // 2

As you can see, the 2nd, 3rd & 4th example above did not render the correct outcome which should be:如您所见,上面的第二个、第三个和第四个示例没有呈现正确的结果,应该是:

console.log(amount('ONEOTW')); // 3
console.log(amount('ONENO')); // 2
console.log(amount('NEOTWONE')); // 4

I'm new to regex, any feedback will be greatly appreciated.我是正则表达式的新手,任何反馈将不胜感激。 Million thanks in advance :)百万提前感谢:)

UPDATE:更新:

Inspired by Trincot, this is a "non-generator" version of the solution:受 Trincot 的启发,这是解决方案的“非生成器”版本:

function permutations(arr) {
  return arr.length === 1
    ? arr
    : arr.flatMap((v,i,a) => permutations([...a.slice(0,i),...a.slice(i+1)]).map((d) => `${v}${d}`));
}

function createRegex(arr) {
  const p = arr.flatMap((v) => permutations([...v]));
  return `(?=${p.join('|')})`;
}

const nums = ['ZERO','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE'];
const regex = createRegex(nums);
const amount = (str) => str.match(RegExp(regex,'g'))?.length || 0;

console.log(amount('TEN')); // 0
console.log(amount('ONE')); // 1
console.log(amount('ONEOTW')); // 3
console.log(amount('ONENO')); // 2
console.log(amount('NEOTWONE')); // 4
console.log(amount('NEOTWONEINEIGHTOWSVEEN')); // 8

You'll have to create a huge regular expression for that:您必须为此创建一个巨大的正则表达式:

First, create all the unique permutations of all input strings ( nums ).首先,创建所有输入字符串 ( nums ) 的所有唯一排列。

Concatenate these into one regular expression, using |使用|将它们连接成一个正则表达式as separator, but use look-ahead, so that one character can be part of a match multiple times.作为分隔符,但使用前瞻,以便一个字符可以多次成为匹配项的一部分。 So for instance, for "ONE", the regular expression would be:例如,对于“ONE”,正则表达式将是:

(?=ONE|OEN|ENO|EON|NEO|NOE)

But then you would also include all permutations of "ZERO" and all the other words.但是,您还将包括“零”和所有其他单词的所有排列。

 function* permutations(word) { if (word.length <= 1) return yield word; for (let i = 0; i < word.length; i++) { for (let perm of permutations(word.slice(0, i) + word.slice(i + 1))) { yield word[i] + perm; } } } function createRegex(words) { const allPermutations = words.flatMap(word => [...new Set(permutations(word))]); return RegExp("(?=" + allPermutations.join("|") + ")", "g"); } function countMatches(regex, phrase) { return phrase.match(regex)?.length ?? 0; } const nums = ['ZERO','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']; const regex = createRegex(nums); for (const test of ['ONE', 'ONEOTW', 'ONENO', 'NEOTWONE']) { console.log(test, countMatches(regex, test)); }

Note that for the second test the answer is 3, not 2, since "NEO" also counts.请注意,第二个测试的答案是 3,而不是 2,因为“NEO”也很重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM