代码之家  ›  专栏  ›  技术社区  ›  totalnoob

使用reduce-javascript重构函数

  •  2
  • totalnoob  · 技术社区  · 6 年前

    我已经编写了一个函数来将“aaazeeee”这样的字符串转换为“aaazeeee”的新字符串

    这就是我试过的代码

    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'));

    如何重构它以使我不需要新的字符串或数组?我试过这样的东西

    const groupCharacters = str => [...str].reduce((accumulator, element) => accumulator[accumulator.length - 1] !== element ? `${accumulator} ` : accumulator + element)

    它输出“AAA”

    我该怎么修复它或者用地图之类的东西代替?

    2 回复  |  直到 6 年前
        1
  •  5
  •   CertainPerformance    6 年前

    改变你的 现有的 代码但仍在使用 reduce ,我建议 减少 进入一个 一串 ,而不是数组:在每次迭代中,与当前字符连接,如果下一个字符已定义且不等于当前字符,则还与空格连接:

    const groupCharacters = str => (
      [...str].reduce((a, char, i) => a + char + (
        str[i + 1] === char || str[i + 1] === undefined
        ? ''
        : ' '
      ), '')
    );
    
    console.log(groupCharacters('aaazeeeee'));

    或者,可以使用一个简单的正则表达式-捕获组中的一个单词字符,然后尽可能多次回溯该组,并替换为整个匹配项加上一个空格:

    const groupCharacters = signature => signature.replace(/(\w)\1*(?!\1|$)/g, '$& ');
    console.log(groupCharacters('aaazeeeee'));

    要分解它:

    • (\w) -匹配任何单词字符,将其捕获到第一组中(以便以后可以使用 \1 )

    • \1* -贪婪地重复刚刚匹配的字符零次或多次(尽可能多地重复)

    • (?!\1|$) -检查刚刚匹配的子字符串后面是否没有字符串结尾或同一字符的另一个结尾。这可以确保最后一个重复的子字符串不会得到附加的空格(也就是说,您不希望 'aaa z eeeee ' )

    作为补充说明,regex \G(\w)\1*+(?!$) 会完成同样的事情,读起来更好,而且效率更高。 \G 匹配最后一个匹配项的结尾或字符串的开头,并且 + 在里面 \1*+ 重复 占有的 ,这意味着,在最后一个子字符串上,引擎将无法回溯,因此一旦检查了最后一个完整的子字符串,引擎将立即失败,而不是先遍历每个字符)。但是,不幸的是,原生js不支持所有格量词,也不支持 \g 锚。

        2
  •  1
  •   vibhor1997a    6 年前

    我会用reduce做这个,就像op想做的那样 reduce -

    function myFunc(str) {
        return str.split('').reduce(function (acc, cv, ci) {
            if (acc.lastElem != cv) {
                acc.str += (acc.lastElem == "") ? cv : ' ' + cv;
            }
            else {
                acc.str += cv;
            }
            acc.lastElem = cv;
            return acc;
        }, { lastElem: '', str: '' }).str;
    }
    console.log(myFunc('aaabbbcc'));
    console.log(myFunc('aaazeeeee'))

    它是怎么工作的?

    累加器是一个带键的对象 lastElem (上一个元素比当前元素)和 str (字符串形成)。