递增字符串中包含的特定数字

Incrementing specific numbers contained within a string

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

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

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

谢谢。

您实际上无法使用 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));

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

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

在JavaScript中,字符串是原始类型,因此是不可变的。默认情况下,在所谓的 "sloppy mode", assigning a value to an element of a string silently fails, but in 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));

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

 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("")
    }

如果您想增加示例字符串的特定部分,您可以使用模式来列出完全匹配项 \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));