【问题标题】:JS array reduce and update neighboring replicasJS数组减少和更新相邻副本
【发布时间】:2021-11-03 16:24:45
【问题描述】:

输入是一个包含三种类型字符串的数组:带有附加数字的字母 L、带有附加数字的字母 R 和带有附加数字的字母 D。这些字符串可能会重复。任务是编写一个函数,该函数将采用相邻的 D 并将它们减少为一个 D,并使用之前存在的 D 的更新数字。 注意只有相邻的 Ds 应该被减少和计数。我想要的输出示例:

input: ['D1', 'D1', 'L1', 'D1', 'D1', 'D1', 'R1']
output: ['D2', 'L1', 'D3', 'R1']

input: ['R1', 'D1', 'L1', 'D1', 'D1', 'D1', 'D1', 'L1', 'R1', 'D1', 'D1', 'D1']
output: ['R1', 'D1', 'L1', 'D4', 'L1', 'R1', 'D3']

显然我的函数不起作用有两个主要原因:在循环时拼接数组(我试图摆脱过多的 Ds),并且我在最后一次迭代时强制函数在数组范围之外查看(arr[i+1].charAt(0) === 'D')。我无法克服这些问题。

function reduceD(arr) {
    for (i = 0; i < arr.length; i++) {
            let str = arr[i];
            if (arr[i].charAt(0) === 'D' && arr[i+1].charAt(0) === 'D') {
              arr[i] = 'D' + (Number(str[1]) + 1);
              arr.splice(i+1, 1); 
          }
        }
    return arr;
}

【问题讨论】:

    标签: javascript arrays duplicates


    【解决方案1】:

    请使用 Array.reduce 函数。

    function reduceD(arr) {
        const result = arr.reduce((total, val) => {
            if(total.length === 0) 
                total.push(val);
            else {
                const last = total[total.length - 1];
                const newValue = last.charAt(0) + (Number(last.slice(1)) + 1);
                last.charAt(0) === val.charAt(0) ? total.splice(total.length - 1, 1, newValue) : total.push(val);
            }
            return total;
        }, []);
        return result;
    }
    
    console.log(reduceD(['D1', 'D1', 'L1', 'D1', 'D1', 'D1', 'R1']));
    console.log(reduceD(['R1', 'D1', 'L1', 'D1', 'D1', 'D1', 'D1', 'L1', 'R1', 'D1', 'D1', 'D1']));

    【讨论】:

      【解决方案2】:

      添加到另一个答案:如果您想在删除元素时迭代数组,请向后执行,这样您就不会错过任何元素。这是您的代码的固定版本和一个简单的循环,恕我直言更容易理解(并且比初学者的另一个答案中的 Array.reduce 函数容易得多)

      不过,我同意另一个答案,即Array.reduce 是更有经验的程序员的出路,他们知道Array.reduce 的工作原理。

      // the fixed version of your code
      function reduceD(arr) {
        // iterate backwards to make the splice possible
        // also note how the loop does never reach i == 0 but stops at 1 instead
        for (let i = arr.length - 1; i > 0; i--) {
          let str = arr[i];
          if (arr[i].charAt(0) === 'D' && arr[i - 1].charAt(0) === 'D') {
            arr[i - 1] = 'D' + (Number(str[1]) + 1);
            arr.splice(i, 1);
          }
        }
        return arr;
      }
      
      // the IMHO simpler way of creating a new array
      function buildingNewArray(arr) {
        let out = [];
        let dsFound = 0;
        for (const elem of arr) {
          if (elem.charAt(0) === 'D') {
            dsFound++;
          } else {
            // there is no D in the current element
            if (dsFound > 0) {
              // add all found Ds as one
              out.push('D' + dsFound);
              dsFound = 0;
            }
            // always output the current element to the output
            out.push(elem);
          }
        }
        // we're done with the loop but there might be some Ds to output
        if (dsFound > 0) {
          out.push('D' + dsFound);
        }
      
        return out;
      }
      
      
      const arr1 = ['D1', 'D1', 'L1', 'D1', 'D1', 'D1', 'R1'];
      const arr2 = ['R1', 'D1', 'L1', 'D1', 'D1', 'D1', 'D1', 'L1', 'R1', 'D1', 'D1', 'D1'];
      console.log(buildingNewArray(arr1));
      console.log(buildingNewArray(arr2));
      console.log(reduceD(arr1));
      console.log(reduceD(arr2));

      【讨论】:

      • 谢谢你,你用反向迭代修复了我的代码,真是太酷了。因为我是初学者,所以更容易理解。非常感谢!
      • 你的第二个解决方案 buildingNewArray 我也喜欢,我盯着它看了一会儿,终于明白了它背后的逻辑。我之前错过的是在将 Ds 推入新数组后将其设置回零的技巧,就像您在循环内使用 dsFound = 0 所做的那样。不错!
      【解决方案3】:

      将数组缩减为一个新数组,如果当前项不是正确的字符,或者累加器中的最后一项 (acc) 不是以正确的字符开头,则压入当前项。否则,增加最后一项的编号。

      const isChar = (char, item) => !!item?.startsWith(char);
      const incItem = item => `${item[0]}${+item.substring(1) + 1}`;
      
      const reduceD = (char, arr) => 
        arr.reduce((acc, c) => {
          if(!isChar(char, c) || !isChar(char, acc[acc.length - 1])) acc.push(c); 
          else acc[acc.length - 1] = incItem(acc[acc.length - 1]);
        
          return acc;
        }, []);
      
      console.log(reduceD('D', ['D1', 'D1', 'L1', 'D1', 'D1', 'D1', 'R1'])); // ['D2', 'L1', 'D3', 'R1']
      
      console.log(reduceD('D', ['R1', 'D1', 'L1', 'D1', 'D1', 'D1', 'D1', 'L1', 'R1', 'D1', 'D1', 'D1'])); // ['R1', 'D1', 'L1', 'D4', 'L1', 'R1', 'D3']

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-03
        • 2014-02-24
        • 2020-05-22
        • 2022-01-27
        • 1970-01-01
        • 2021-03-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多