#javascript #string #increment
#javascript #строка #приращение
Вопрос:
Я работаю со строками, которые выглядят следующим образом:
"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));
Несмотря на успешное увеличение чисел, значение строки не изменяется.
Спасибо.
Комментарии:
1. Из любопытства, что приводит вас к выводу, что числа успешно увеличиваются, если значение строки не изменяется?
2. Я только что добавил закомментированную строку в свой приведенный выше код, демонстрирующую, из какой строки я почерпнул это понимание
Ответ №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:
В JavaScript строка является примитивным типом и поэтому неизменяема. По умолчанию, в так называемом «небрежном режиме», присвоение значения элементу строки автоматически завершается ошибкой, но в строгом режиме это приведет к ошибке:
"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 amp;amp; (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));
Ответ №3:
Я немного изменил ваш код, и я думаю, что теперь он работает!
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 amp;amp; is_numeric(arr[i])) {
if (arr[i - 1] !== undefined amp;amp; arr[i - 1] !== "/" amp;amp; 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 amp;amp; is_numeric(arr[i])) {
if (arr[i - 1] !== undefined amp;amp; arr[i - 1] !== "/" amp;amp; arr[i - 1] !== "x") {
arr[i] = "" (parseInt(arr[i]) 1);
}
}
}
return arr.join("")
}
Ответ №4:
Если вы хотите увеличить определенную часть строки примера, вы можете использовать шаблон для перечисления точных совпадений 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"));
Для указания точки как количества символов, которое должно быть после начала строки, вы можете использовать lookbehind, для которого поддерживается этот браузер, и динамический шаблон для установки 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));
Ответ №5:
Вы не можете изменить символ в строке по индексу напрямую. Например:
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));