首页>Program>source

我想比较两个字符串(前后一个字符串),并准确检测它们之间的位置和变化。

对于任何更改,我想知道:

  1. 更改的开始位置(包括0,从0开始)
  2. 更改相对于上一个文本的结束位置(包括0,从0开始)
  3. "变化"

假定字符串一次只能更改一个位置(例如,从不" B 伊尔维兹 "->" l 伊尔维兹 ")。

此外,我需要开始和结束位置以反映更改的类型:

K

例如:

n

我能够在某种程度上检测到更改后的文本的位置,但是它不能在所有情况下都起作用,因为要准确地执行此操作,我需要知道进行了哪种更改。

  • If deletion, the start and end position should be the start and end positions of the deleted text, respectively
  • If replacement, the start and end position should be the start and end positions of the "deleted" text, respectively (the change will be the "added" text)
  • If insertion, the start and end positions should be the same; the entry point of the text
  • If no change, let start and end positions remain zero, with an empty change

"0123456789" -> "03456789" Start: 1, End: 2, Change: "" (deletion) "03456789" -> "0123456789" Start: 1, End: 1, Change: "12" (insertion) "Hello World!" -> "Hello Aliens!" Start: 6, End: 10, Change: "Aliens" (replacement) "Hi" -> "Hi" Start: 0, End: 0, Change: "" (no change)


我已经搜索并提出了很少< a href =" https://stackoverflow.com/questions/25706571/which-part-of-strings-are-different-javascript">其他类似问题,但它们似乎无济于事。

var OldText = "My edited string!"; var NewText = "My first string!"; var ChangeStart = 0; var NewChangeEnd = 0; var OldChangeEnd = 0; console.log("Comparing start:"); for (var i = 0; i < NewText.length; i++) { console.log(i + ": " + NewText[i] + " -> " + OldText[i]); if (NewText[i] != OldText[i]) { ChangeStart = i; break; } } console.log("Comparing end:"); // "Addition"? if (NewText.length > OldText.length) { for (var i = 1; i < NewText.length; i++) { console.log(i + "(N: " + (NewText.length - i) + " O: " + (OldText.length - i) + ": " + NewText.substring(NewText.length - i, NewText.length - i + 1) + " -> " + OldText.substring(OldText.length - i, OldText.length - i + 1)); if (NewText.substring(NewText.length - i, NewText.length - i + 1) != OldText.substring(OldText.length - i, OldText.length - i + 1)) { NewChangeEnd = NewText.length - i; OldChangeEnd = OldText.length - i; break; } } // "Deletion"? } else if (NewText.length < OldText.length) { for (var i = 1; i < OldText.length; i++) { console.log(i + "(N: " + (NewText.length - i) + " O: " + (OldText.length - i) + ": " + NewText.substring(NewText.length - i, NewText.length - i + 1) + " -> " + OldText.substring(OldText.length - i, OldText.length - i + 1)); if (NewText.substring(NewText.length - i, NewText.length - i + 1) != OldText.substring(OldText.length - i, OldText.length - i + 1)) { NewChangeEnd = NewText.length - i; OldChangeEnd = OldText.length - i; break; } } // Same length... } else { // Do something } console.log("Change start: " + ChangeStart); console.log("NChange end : " + NewChangeEnd); console.log("OChange end : " + OldChangeEnd); console.log("Change: " + OldText.substring(ChangeStart, OldChangeEnd + 1));
最新回答
  • 7月前
    1 #

    我遍历了您的代码,并且您匹配字符串的逻辑对我来说很有意义.它记录 ChangeStart ,威兹威兹   和 NewChangeEnd   正确,算法可以正常进行.您只想知道一个 OldChangeEnd ,威兹威兹   或 insertion   发生.这就是我的处理方法。

    首先,您需要确定错配的第一点,即 deletion   当您从头开始遍历字符串时,索引不应越过 replacement

    我给你举个例子.考虑以下字符串:

    ChangeStart
    

    在这种情况下,问题是当它从背面开始匹配时,流程是这样的:

    ChangeStart
    

    假设,我刚才说的很有意义,您只需要修改 var NewText = "Hello Worllolds!"; var OldText = "Hello Worlds!"; ChangeStart -> 10 //Makes sense OldChangeEnd -> 8 NewChangeEnd -> 11 console.log("Change: " + NewText.substring(ChangeStart, NewChangeEnd + 1)); //Ouputs "lo"   像这样循环:

    Comparing end: 
      1(N: 12 O: 12: ! -> !) 
      2(N: 11 O: 11: s -> s) 
      3(N: 10 O: 10: d -> d)  -> You need to stop here!
     //Although there is not a mismatch, but we have reached ChangeStart and 
     //we have already established that characters from 0 -> ChangeStart-1 match
     //That is why it outputs "lo" instead of "lol"
    

    这种情况-> for   维护我提到的异常,因此 if (NewText.length > OldText.length) { for (var i = 1; i < NewText.length && ((OldText.length-i)>=ChangeStart); i++) { ... NewChangeEnd = NewText.length - i -1; OldChangeEnd = OldText.length - i -1; if(//Mismatch condition reached){ //break..That code is fine. } }   如果达到此条件,循环将自动终止.但是,正如我提到的那样,在某些情况下,如我刚刚演示的那样,在遇到不匹配之前可能已经达到此条件.所以你需要更新 (OldText.length-i)>=ChangeStart的值   和 for   比维兹威兹少1   值.如果不匹配,请适当存储值。

    代替维兹维兹   我们可以在知道 NewChangeEnd的情况下包装这两个条件   绝对是 OldChangeEnd   真实,即它既是维兹维兹   或 matched .再一次 else -if   也意味着它可能是个 NewText.length > OldText.length   或 not   根据您的示例,这很有意义.因此, replacement   可能是这样的:

    deletion
    

    如果您到目前为止已经了解了微小的变化,那么确定具体情况就非常简单:

    NewText.length > OldText.length   -条件-> replacement .从 insertion中删除了字符串 .

    已删除的文字-> else

    else { for (var i = 1; i < OldText.length && ((OldText.length-i)>=ChangeStart); i++) { ... NewChangeEnd = NewText.length - i -1; OldChangeEnd = OldText.length - i -1; if(//Mismatch condition reached){ //break..That code is fine. } }   -条件-> Deletion .在 ChangeStart > NewChangeEnd插入字符串 .

    插入文字-> ChangeStart -> OldChangeEnd

    OldText.substring(ChangeStart, OldChangeEnd + 1);   -如果 Insertion   以上两个条件是 ChangeStart > OldChangeEnd   遇见,然后它 ChangeStart   一个替代品.

    已替换的旧字符串中的文本-> NewText.substring(ChangeStart, NewChangeEnd + 1);

    替换文字-> Replacement

    NewText != OldText中的开始和结束位置   那有 not   ->威兹威兹

    我创建了一个jsfiddle,其中包含了我在您的代码中提到的更改.您可能需要检查一下.希望它可以帮助您朝正确的方向开始。

  • 7月前
    2 #

    我遇到了类似的问题,并通过以下方法解决了该问题:

    is
    

    请注意,虽然这并不能解决我的实际问题.我的问题是我有一个带有段落的编辑器,每个段落都以文本为模型,并用开始和结束索引定义了一组标记,例如 从char 1到char 5的粗体。我使用它来检测字符串的更改,以便可以相应地更改标记索引.但是考虑一下字符串:

    xx OldText.substring(ChangeStart, OldChangeEnd + 1); xx

    diff函数方法无法分辨加在粗体外或内的字符之间的区别。

    最后,我采用了一种完全不同的方法-我只是解析了编辑器生成的HTML,并用它来确定标记的开始和结束索引。

  • 7月前
    3 #

    我制作了性能稍高的版本 受到与上述相同策略的启发(寻找前后之间以及前后之间的差异)

    NewText.substring(ChangeStart, NewChangeEnd + 1);
    
    OldText

  • asp.net mvc:如何通过URL传递日期,以便在MVC中读取我的操作?
  • javascript:是否有JS函数可查找小数点前后的值