【问题标题】:Incrementing specific numbers contained within a string递增字符串中包含的特定数字
【发布时间】:2021-05-29 10:57:19
【问题描述】:

我正在使用如下所示的字符串:

"do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4"

我想将字符串中的每个数字递增到一个特定点,以排除“/”或“x”旁边的数字。例如,如果我想将上述字符串的所有数字递增到点 do3mi3so3 之后,我希望得到这个:

"do3mi3so3 la4 ti5 do6 re6 mi6 /2 x2 fa5"

这是我的代码:

function is_numeric(str){
    return /^\d+$/.test(str);
}


function change_octave(notes,split_point){
  for(var i=(split_point-1);i<notes.length;i++){
    if(is_numeric(notes[i])==true){
      notes[i]='' + parseInt(notes[i])+1;
      //console.log(parseInt(notes[i])+1) //these numbers are incrementing
    }
    if(notes[i]=='/'||notes[i]=='x'){
      i = i+3;
    }
  }
  return notes;
}
var notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
console.log(change_octave(notes,4));

尽管数字成功递增,但字符串的值不会改变。

谢谢。

【问题讨论】:

  • 出于好奇,如果字符串的值没有改变,是什么让您得出结论数字成功递增?
  • 我刚刚在上面的代码中添加了一个注释掉的行,展示了我从哪一行收集到的见解

标签: javascript string increment


【解决方案1】:

您实际上不能使用notes[i] = "a" 之类的东西在特定索引处设置字符串的字符。您可以做的是将字符串拆分为一个数组,更改该数组中的值,然后在完成后将其重新组合成一个字符串。

function is_numeric(str){
    return /^\d+$/.test(str);
}

function change_octave(notesStr,split_point){
  const notes = notesStr.split('');
  for(var i=(split_point-1);i<notes.length;i++){
    if(is_numeric(notes[i])==true){
      const newValue = parseInt(notes[i]) + 1;
      notes[i] = '' + newValue;
    }
    if(notes[i]=='/'||notes[i]=='x'){
      i = i+3;
    }
  }
  return notes.join('');
}
var notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
console.log(change_octave(notes,4));

【讨论】:

    【解决方案2】:

    您不能直接通过索引更改字符串中的字符。例如:

       notes="aaa"
       notes[1] = "b"
       console.log(notes)
    

    解决办法是:

    function is_numeric(str){
        return /^\d+$/.test(str);
    }
    
    
    function change_octave(notes,split_point){
      modified_notes = notes.split('')
      for(var i=(split_point-1);i<notes.length;i++){
        if(is_numeric(notes[i])==true){
          modified_notes[i]=''+(parseInt(notes[i])+1);
          //console.log(parseInt(notes[i])+1) //these numbers are incrementing
        }
        if(notes[i]=='/'||notes[i]=='x'){
          i = i+3;
        }
      }
      
      return  modified_notes.join('')  
    }
    var notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
    console.log(change_octave(notes,4));

    【讨论】:

      【解决方案3】:

      在 JavaScript 中,字符串是一种原始类型,因此是不可变的。默认情况下,在所谓的"sloppy mode" 中,为字符串的元素赋值会静默失败,但在strict mode 中会抛出错误:

      "use strict";
      let notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
      notes[4] = "o";

      为了做到这一点,我建议像这样使用String.prototype.replace()

      function change_octave(notes, split_point) {
        return notes.replace(/\d+/g, (str, i) => {
          if (--split_point > 0) {
            return str;
          }
      
          if (i > 0 && (notes[i - 1] === '/' || notes[i - 1] === 'x')) {
            return str;
          }
      
          return Number(str) + 1;
        });
      }
      
      let notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
      
      console.log(change_octave(notes, 4));

      【讨论】:

        【解决方案4】:

        我稍微修改了你的代码,我认为它现在可以工作了!

         function is_numeric(str) {
                return /^\d+$/.test(str);
            }
        
            function change(note, point) {
                var arr = note.split("")
                var ind = note.indexOf(point)
                ind = ind + point.length -1;
                for (var i = 0; i < arr.length; i++) {
                    if (i > ind && is_numeric(arr[i])) {
                        if (arr[i - 1] !== undefined && arr[i - 1] !== "/" && arr[i - 1] !== "x") {
                            arr[i] = "" + (parseInt(arr[i]) + 1);
                        }
                    }
                }
                return arr.join("")
            }
            var notes = "do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4";
            console.log(change(notes, "do3mi3so3"))
        

        输出:

        do3mi3so3 la4 ti5 do6 re6 mi6 /2 x2 fa5
        

        如果你想使用索引位置作为点,那么

        function change(note, point) {
                var arr = note.split("")
                var ind = point
                for (var i = 0; i < arr.length; i++) {
                    if (i > ind && is_numeric(arr[i])) {
                        if (arr[i - 1] !== undefined && arr[i - 1] !== "/" && arr[i - 1] !== "x") {
                            arr[i] = "" + (parseInt(arr[i]) + 1);
                        }
                    }
                }
                return arr.join("")
            }
        

        【讨论】:

          【解决方案5】:

          如果你想增加示例字符串的特定部分,你可以使用一个模式来列出精确匹配 \b([ds]o|re|mi|fa|la|ti)\b 并使用单词边界来防止部分匹配。

          replace的回调中,可以增加数字的组匹配。

          let regex = /\b([ds]o|re|mi|fa|la|ti)(\d+)\b/g;
          const change_octave = notes => notes.replace(regex, (_, g1, g2) => g1 + ++g2);
          
          console.log(change_octave("do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4"));

          为了将点指定为字符串开头之后的字符数,您可以使用后向查找,即 browser support 和动态模式来设置 point

          const change_octave = (notes, point) => {
            let regex = new RegExp(`(?<=^.{${point}}.*\\b(?:[ds]o|re|mi|fa|la|ti))\\d+\\b`, "g");
            return notes.replace(regex, m => ++m);
          }
          
          console.log(change_octave("do3mi3so3 la3 ti4 do5 re5 mi5 /2 x2 fa4", 4));
          console.log(change_octave("la3 ti4 do5 re5 mi5 /2 x2 fa4", 4));

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-01-09
            • 2022-11-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多