我想识别由相同长度的字符组组成的字符串.这些组中的每一个都包含至少两个相同的字符.所以,这里有一些例子:
aabbcc true
abbccaa false
xxxrrrruuu false (too many r's)
xxxxxfffff true
aa true (shortest possible positive example)
aabbbbcc true // I added this later to clarify my intention
Run Code Online (Sandbox Code Playgroud)
@ilkkachu:感谢您关于重复相同角色组的评论.我添加了上面的例子.是的,我希望将最后一个样本测试为true:由两个字母组组成的字符串aa, bb, bb, cc.
是否有一种简单的方法可以使用正则表达式和JavaScript对字符串应用此条件检查?
我的第一次尝试是做类似的事情
var strarr=['aabbcc','abbccaa','xxxrrrruuu',
'xxxxxfffff','aa','negative'];
var rx=/^((.)\2+)+$/;
console.log(strarr.map(str=>str+': '+!!str.match(rx)).join('\n'));
Run Code Online (Sandbox Code Playgroud)
它确实查找重复字符的组,但不不还关注这些群体的所有作为的长度相同,如输出所示:
aabbcc: true
abbccaa: false
xxxrrrruuu: true // should be false!
xxxxxfffff: true
aa: true
aabbbbcc: true
negative: false
Run Code Online (Sandbox Code Playgroud)
如何检查以查找相同长度的字符组?
要获得相同角色的所有组,可以使用简单的正则表达式解决方案:
/(.)\1*/g
Run Code Online (Sandbox Code Playgroud)
只需重复\1捕获组1中角色的反向引用.
然后检查数组中是否存在不匹配的相同字符串的长度.
示例代码段:
function sameLengthCharGroups(str)
{
if(!str) return false;
let arr = str.match(/(.)\1*/g) //array with same character strings
.map(function(x){return x.length}); //array with lengths
let smallest_length = arr.reduce(function(x,y){return x < y ? x : y});
if(smallest_length === 1) return false;
return arr.some(function(n){return (n % smallest_length) !== 0}) == false;
}
console.log("-- Should be true :");
let arr = ['aabbcc','xxxxxfffff','aa'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should also be true :");
arr = ['aabbbbcc','224444','444422',
'666666224444666666','666666444422','999999999666666333'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should be false :");
arr = ['abbcc','xxxrrrruuu','a','ab','',undefined];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});Run Code Online (Sandbox Code Playgroud)
带有胖箭头的ECMAScript 6版本(在IE中不起作用)
function sameLengthCharGroups(str)
{
if(!str) return false;
let arr = str.match(/(.)\1*/g)
.map((x) => x.length);
let smallest_length = arr.reduce((x,y) => x < y ? x : y);
if(smallest_length === 1) return false;
return arr.some((n) => (n % smallest_length) !== 0) == false;
}
Run Code Online (Sandbox Code Playgroud)
或者使用exec代替匹配,对于大字符串应该更快.
因为它可以在找到不同长度后立即退出while循环.
但这样做的缺点是,在比较它们之前,它无法获得所有长度的最小长度.
所以那些最后长度最小的人就不会这样.
function sameLengthCharGroups(str)
{
if(!str) return false;
const re = /(.)\1*/g;
let m, smallest_length;
while(m = re.exec(str)){
if(m.index === 0) {smallest_length = m[0].length}
if(smallest_length > m[0].length && smallest_length % m[0].length === 0){smallest_length = m[0].length}
if(m[0].length === 1 ||
// m[0].length !== smallest_length
(m[0].length % smallest_length) !== 0
) return false;
}
return true;
}
console.log("-- Should be true :");
let arr = ['aabbcc','xxxxxfffff','aa'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should also be true :");
arr = ['aabbbbcc','224444','444422',
'666666224444666666','666666444422','999999999666666333'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should be false :");
arr = ['abbcc','xxxrrrruuu','a','ab','',undefined];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});Run Code Online (Sandbox Code Playgroud)
这是一个在线性时间运行的:
function test(str) {
if (str.length === 0) return true;
let lastChar = str.charAt(0);
let seqLength = 1;
let lastSeqLength = null;
for (let i = 1; i < str.length; i++) {
if (str.charAt(i) === lastChar) {
seqLength++;
}
else if (lastSeqLength === null || seqLength === lastSeqLength) {
lastSeqLength = seqLength;
seqLength = 1;
lastChar = str.charAt(i);
}
else {
return false;
}
}
return (lastSeqLength === null || lastSeqLength === seqLength);
}
Run Code Online (Sandbox Code Playgroud)