Skip to content

Commit c55cf50

Browse files
authored
Merge pull request #48 from sergi/46-refactor-diffHalfMatchI-and-remove-concat
Refactor diff half match i and remove concat
2 parents ff694a8 + c6f74d9 commit c55cf50

File tree

2 files changed

+40
-39
lines changed

2 files changed

+40
-39
lines changed

diffmatchpatch/dmp.go

+30-39
Original file line numberDiff line numberDiff line change
@@ -798,60 +798,51 @@ func (dmp *DiffMatchPatch) diffHalfMatch(text1, text2 []rune) [][]rune {
798798
return [][]rune{hm[2], hm[3], hm[0], hm[1], hm[4]}
799799
}
800800

801-
// diffHalfMatchI checks if a substring of shorttext exist within longtext such that the substring is at least half the length of longtext?
801+
// diffHalfMatchI checks if a substring of shorttext exist within longtext such that the substring is at least half the length of longtext?
802802
// @param {string} longtext Longer string.
803803
// @param {string} shorttext Shorter string.
804804
// @param {number} i Start index of quarter length substring within longtext.
805805
// @return {Array.<string>} Five element Array, containing the prefix of
806806
// longtext, the suffix of longtext, the prefix of shorttext, the suffix
807807
// of shorttext and the common middle. Or null if there was no match.
808808
func (dmp *DiffMatchPatch) diffHalfMatchI(l, s []rune, i int) [][]rune {
809+
var bestCommonA []rune
810+
var bestCommonB []rune
811+
var bestCommonLen int
812+
var bestLongtextA []rune
813+
var bestLongtextB []rune
814+
var bestShorttextA []rune
815+
var bestShorttextB []rune
816+
809817
// Start with a 1/4 length substring at position i as a seed.
810818
seed := l[i : i+len(l)/4]
811-
j := -1
812-
bestCommon := []rune{}
813-
bestLongtextA := []rune{}
814-
bestLongtextB := []rune{}
815-
bestShorttextA := []rune{}
816-
bestShorttextB := []rune{}
817-
818-
if j < len(s) {
819-
j = runesIndexOf(s, seed, j+1)
820-
for {
821-
if j == -1 {
822-
break
823-
}
824819

825-
prefixLength := commonPrefixLength(l[i:], s[j:])
826-
suffixLength := commonSuffixLength(l[:i], s[:j])
827-
if len(bestCommon) < suffixLength+prefixLength {
828-
bestCommon = concat(s[j-suffixLength:j], s[j:j+prefixLength])
829-
bestLongtextA = l[:i-suffixLength]
830-
bestLongtextB = l[i+prefixLength:]
831-
bestShorttextA = s[:j-suffixLength]
832-
bestShorttextB = s[j+prefixLength:]
833-
}
834-
j = runesIndexOf(s, seed, j+1)
820+
for j := runesIndexOf(s, seed, 0); j != -1; j = runesIndexOf(s, seed, j+1) {
821+
prefixLength := commonPrefixLength(l[i:], s[j:])
822+
suffixLength := commonSuffixLength(l[:i], s[:j])
823+
824+
if bestCommonLen < suffixLength+prefixLength {
825+
bestCommonA = s[j-suffixLength : j]
826+
bestCommonB = s[j : j+prefixLength]
827+
bestCommonLen = len(bestCommonA) + len(bestCommonB)
828+
bestLongtextA = l[:i-suffixLength]
829+
bestLongtextB = l[i+prefixLength:]
830+
bestShorttextA = s[:j-suffixLength]
831+
bestShorttextB = s[j+prefixLength:]
835832
}
836833
}
837834

838-
if len(bestCommon)*2 >= len(l) {
839-
return [][]rune{
840-
bestLongtextA,
841-
bestLongtextB,
842-
bestShorttextA,
843-
bestShorttextB,
844-
bestCommon,
845-
}
835+
if bestCommonLen*2 < len(l) {
836+
return nil
846837
}
847-
return nil
848-
}
849838

850-
func concat(r1, r2 []rune) []rune {
851-
result := make([]rune, len(r1)+len(r2))
852-
copy(result, r1)
853-
copy(result[len(r1):], r2)
854-
return result
839+
return [][]rune{
840+
bestLongtextA,
841+
bestLongtextB,
842+
bestShorttextA,
843+
bestShorttextB,
844+
append(bestCommonA, bestCommonB...),
845+
}
855846
}
856847

857848
// DiffCleanupSemantic reduces the number of edits by eliminating

diffmatchpatch/dmp_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,16 @@ func Benchmark_DiffMainLargeLines(b *testing.B) {
15521552
}
15531553
}
15541554

1555+
func Benchmark_DiffHalfMatch(b *testing.B) {
1556+
s1 := readFile("speedtest1.txt", b)
1557+
s2 := readFile("speedtest2.txt", b)
1558+
dmp := New()
1559+
b.ResetTimer()
1560+
for i := 0; i < b.N; i++ {
1561+
dmp.DiffHalfMatch(s1, s2)
1562+
}
1563+
}
1564+
15551565
func readFile(filename string, b *testing.B) string {
15561566
bytes, err := ioutil.ReadFile(filename)
15571567
if err != nil {

0 commit comments

Comments
 (0)