我已经编写了一个函数来将诸如'aaazeeeee'之类的字符串转换为'aaa z eeeee'的新字符串
这是我尝试过的代码
const groupCharacters = signature => {
let newSignature = "", arr = [];
let result = [...signature].reduce((accumulator, element, index) => {
// check if last element in accumulator matches current element
if (accumulator[accumulator.length -1] !== element) {
// push accumulator into array
arr.push(accumulator);
// set newSignature as new element
newSignature = element;
} else {
// else add element to newSignature
newSignature = accumulator += element;
}
// if is last item, push to array
if (index === signature.length - 1) arr.push(element);
return newSignature;
})
return arr;
}
console.log(groupCharacters('aabaaaaa'));Run Code Online (Sandbox Code Playgroud)
我怎么能重构它以便我不需要新的字符串或数组?我尝试过这样的事情
const groupCharacters = str => [...str].reduce((accumulator, element) => accumulator[accumulator.length - 1] !== element ? `${accumulator} ` : accumulator + element)Run Code Online (Sandbox Code Playgroud)
它输出'aaa'
我该如何解决它或者使用像地图这样的东西呢?
要更改现有代码但仍然使用reduce,我建议reduce使用字符串,而不是数组:在每次迭代时,与当前字符连接,如果下一个字符都被定义并且不等于当前的角色:
const groupCharacters = str => (
[...str].reduce((a, char, i) => a + char + (
str[i + 1] === char || str[i + 1] === undefined
? ''
: ' '
), '')
);
console.log(groupCharacters('aaazeeeee'));Run Code Online (Sandbox Code Playgroud)
或者,您可以使用简单的正则表达式 - 捕获组中的单词字符,然后尽可能多地反向引用该组,并替换为整个匹配和空格:
const groupCharacters = signature => signature.replace(/(\w)\1*(?!\1|$)/g, '$& ');
console.log(groupCharacters('aaazeeeee'));Run Code Online (Sandbox Code Playgroud)
要打破它:
(\w)- 匹配任何单词字符,在第一组中捕获它(以便以后可以反向引用\1)
\1* - 贪婪地重复刚刚匹配零次或多次的角色(尽可能重复)
(?!\1|$) - 检查刚刚匹配的子字符串是否后跟字符串的结尾或其他相同的字符.这可以确保最终重复的子字符串也不会附加空格(也就是说,您不需要'aaa z eeeee ').
作为旁注,正则表达式\G(\w)\1*+(?!$)将完成同样的事情,更好阅读,并且显着更高效(\G匹配结束最后一个匹配或字符串的开头,并且+in \1*+使得重复占有,这意味着,在最后的子字符串上,引擎将无法回溯,因此一旦检查完最终的完整子字符串就会立即失败,而不是首先迭代其每个字符).但是,遗憾的是,原生JS不支持占有量词,也不支持\G锚.
| 归档时间: |
|
| 查看次数: |
67 次 |
| 最近记录: |