简体   繁体   English

如何不替换已经替换的单词

[英]How to not replace the word that has already been replaced

This is my code: 这是我的代码:

<script>
    function TransposeDown() {
        $("body").html($("body").html().replace(/C/g, 'B'));
        $("body").html($("body").html().replace(/B/g, 'Bb'));
    }
</script>

<button onclick="TransposeDown();">Transpose Down</button>
<span class="hcrd">C</span>
<span class="hcrd">B</span>
<span class="hcrd">C</span>

The problem is that once the button is clicked, the text inside all the <span> tags change to "Bb". 问题是,一旦button被点击时,所有的内文<span>标签更改为“BB”。 But what I want is the first and the last span 's text to change to "B" and the second one's text to change to "Bb" only. 但是我想要的是第一个和最后一个span的文本更改为“ B”,而第二个的文本仅更改为“ Bb”。

How do I do this? 我该怎么做呢? Is there any way to do this in such a way that the function is done only once? 有没有办法只执行一次功能呢? Any help is appreciated. 任何帮助表示赞赏。

You can either invert, which works in simple instances, or you can do it like this, which works even in complex instances: 您可以反转(在简单实例中可以使用),也可以像这样进行甚至在复杂实例中也可以使用:

var string = "A B C D";

string = string.replace(/(C)|(B)/g,function(str,p1,p2) {
    if(p1) return 'B';
    if(p2) return 'Bb';
});

So in your case, it would be: 因此,在您的情况下,它将是:

 $("body").html($("body").html().replace(/(C)|(B)/g,function(str,p1,p2) {
    if(p1) return 'B';
    if(p2) return 'Bb';
 }));

Since you are obviously trying to transpose musical chords, I'd go for a solution using data-original to store the original note, and keep track of how many times the user has transposed the notes. 由于您显然是在尝试移调和弦,因此我将寻求一种使用data-original的解决方案来存储原始音符,并跟踪用户移调音符的次数。 This way you can easily reset the whole thing. 这样,您可以轻松地重置整个事情。

Working example: https://jsfiddle.net/dannyjolie/b5ghxLoL/1/ 工作示例: https : //jsfiddle.net/dannyjolie/b5ghxLoL/1/

Update: Out of the box, this doesn't work with any 6th, 7th, maj, min etc, but this can also be stored as a data attribute, and be appended to the output. 更新:开箱即用,不适用于第6,第7,maj,min等,但是也可以将其存储为data属性,并附加到输出中。

 var notes = ["A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab"]; var transposed = 0; function transpose() { var chords = document.querySelectorAll('.hcrd'); var chord = ''; for (var i = 0; i < chords.length; i++) { chord = chords[i].dataset['original']; chords[i].innerHTML = getNewChord(chord); } } function getNewChord(chord) { var origIndex = notes.indexOf(chord); if (origIndex === -1) { // Invalid chord return chord; } if (origIndex + transposed < 0) { return notes[notes.length + transposed + origIndex]; } return notes[origIndex + transposed]; } function transposeDown() { transposed -= 1; if(transposed === -12){ transposed = 0; } transpose(); } function reset() { transposed = 0; transpose(); } document.querySelector('#transposedown').addEventListener('click', transposeDown, false); document.querySelector('#reset').addEventListener('click', reset, false) 
 <span class="hcrd" data-original="C">C</span> <span class="hcrd" data-original="B">B</span> <span class="hcrd" data-original="C">C</span> <span class="hcrd" data-original="G">G</span> <span class="hcrd" data-original="E">E</span> <button id="transposedown">Transpose down</button> <button id="reset">Reset</button> 

Simply invert your two methods, starting with the B replacement then with the C one: 简单地颠倒您的两种方法,从替换B开始,然后到替换C:

function TransposeDown() {
    $("body").html($("body").html().replace(/B/g, 'Bb'));
    $("body").html($("body").html().replace(/C/g, 'B'));
}

You could also transpose to a special pattern (for example prefixing all transpositions by a special tag) then make sure to exclude this tag from the regexes. 您也可以转置为特殊模式(例如,使用特殊标记在所有转置之前添加前缀),然后确保从正则表达式中排除此标记。 Finally, remove the special pattern from the whole document. 最后,从整个文档中删除特殊模式。 This would take longer, but would allow you to not take order into account 这将花费更长的时间,但是将使您不考虑订单

As a more general solution, you could consider writing a regex that matches both and using a function to determine the replacement. 作为更通用的解决方案,您可以考虑编写同时匹配两者的正则表达式并使用函数确定替换项。 This would work for arbitrary search/replace as it does it all in one pass. 这将适用于任意搜索/替换,因为它一次完成所有操作。

$("body").html($("body").html().replace(/(B|C)/g, function(match) {
  switch (match) {
    case 'B':
      return 'Bb';
    case 'C':
      return 'B';
  }
));

You should change them in sequence by selecting them all with a common selector, then skip the change if the element has changed. 您应该通过使用通用选择器全部选择它们来顺序更改它们,如果元素已更改,则跳过更改。

 var rules = [{ regEx: /^C$/g, str: 'B' }, { regEx: /^B$/g, str: 'Bb' }]; function TransposeDown() { $(".hcrd").each(function(index, el) { var $el = $(el); var prevVal = $(el).html(); var newVal = ''; for (var i = 0; i < rules.length; i++) { newVal = $el.html().replace(rules[i].regEx, rules[i].str); if (newVal != prevVal) { $el.html(newVal); break; } } }); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button onclick="TransposeDown();">Transpose Down</button> <span class="hcrd">C</span> <span class="hcrd">B</span> <span class="hcrd">C</span> 

I would do it differently.. 我会做不同的事情。

<script>
function TransposeDown(){
     $("#C").html(text.replace("C", "B"));
     $("#B").html(text.replace("B", "Bb"));
}
</script>

<button onclick="TransposeDown();">Transpose Down</button>
<span class="hcrd" id="C">C</span>
<span class="hcrd" id="B">B</span>
<span class="hcrd" id="C">C</span>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM