Skip to content

Commit

Permalink
feature: use myers's difference alogorithm to improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
wzxha committed Dec 14, 2018
1 parent 3246d71 commit 26f1a89
Show file tree
Hide file tree
Showing 13 changed files with 528 additions and 356 deletions.
56 changes: 43 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,56 @@
[![codecov](https://codecov.io/gh/Wzxhaha/Sdifft/branch/master/graph/badge.svg)](https://codecov.io/gh/Wzxhaha/Sdifft)
[![codebeat badge](https://codebeat.co/badges/d37a19b5-3d38-45ae-a7c5-5e453826188d)](https://codebeat.co/projects/github-com-wzxhaha-sdifft-master)

Using the LCS to compare differences between two strings
Using [`the Myers's Difference Algorithm`](http://www.xmailserver.org/diff2.pdf) to compare differences between two equatable element

## Example
## Example(String)

```swift
impoort Sdifft

let to = "abcd"
let from = "b"
let diff = Diff(from: from, to: to)
/// Get diff modifications
diff.modifications // [(add: "a", delete: nil, same: "b"), (add: "cd", delete: nil, same: nil)]

/// Get same/add/delete
let same = diff.modifications.compactMap { $0.same }
...
let source = "b"
let target = "abcd"
let diff = Diff(source: from, target: to)
diff.scripts // [.insert(into: 3), .insert(into: 2), .same(into: 1), .insert(into: 0)]

/// Get diff attributedString
let diffAttributes = DiffAttributes(add: [.backgroundColor: UIColor.green]], delete: [.backgroundColor: UIColor.red], same: [.backgroundColor: UIColor.white])
let attributedString = NSAttributedString.attributedString(with: diff, attributes: diffAttributes)
let diffAttributes =
DiffAttributes(
insert: [.backgroundColor: UIColor.green]],
delete: [.backgroundColor: UIColor.red],
same: [.backgroundColor: UIColor.white]
)
let attributedString = NSAttributedString(source: source, target: target, attributes: diffAttributes)

// output ->
// a{green}b{black}cd{green}
```

## Example(Line)

```swift
impoort Sdifft
let source = ["Hello"]
let target = ["Hello", "World", "!"]
let attributedString =
NSAttributedString(source: source, target: target, attributes: diffAttributes) {
let string = NSMutableAttributedString(attributedString: string)
string.append(NSAttributedString(string: "\n"))
switch script {
case .delete:
string.insert(NSAttributedString(string: "- "), at: 0)
case .insert:
string.insert(NSAttributedString(string: "+ "), at: 0)
case .same:
string.insert(NSAttributedString(string: " "), at: 0)
}
return string
}

// output ->
// Hello
// + World{green}
// + !{green}
```

## Installation
Expand Down
40 changes: 40 additions & 0 deletions Sdifft.playground/Contents.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import UIKit
import Sdifft

// Difference between two strings
let source = "Hallo world"
let target = "typo: Hello World!"

let font = UIFont.systemFont(ofSize: 20)
let insertAttributes: [NSAttributedString.Key: Any] = [
.backgroundColor: UIColor.green,
.font: font
]
let deleteAttributes: [NSAttributedString.Key: Any] = [
.backgroundColor: UIColor.red,
.font: font,
.strikethroughStyle: NSUnderlineStyle.single.rawValue,
.strikethroughColor: UIColor.red,
.baselineOffset: 0
]

let sameAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.black,
.font: font
]

let attributedString1 =
NSAttributedString(
source: source, target: target,
attributes: DiffAttributes(insert: insertAttributes, delete: deleteAttributes, same: sameAttributes)
)

// Difference between two lines
let sourceLines = ["I'm coding with Swift"]
let targetLines = ["Today", "I'm coding with Swift", "lol"]

let attributedString2 =
NSAttributedString(
source: sourceLines, target: targetLines,
attributes: DiffAttributes(insert: insertAttributes, delete: deleteAttributes, same: sameAttributes)
)
4 changes: 4 additions & 0 deletions Sdifft.playground/contents.xcplayground
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'>
<timeline fileName='timeline.xctimeline'/>
</playground>
8 changes: 3 additions & 5 deletions Sdifft.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
1E4BF61B21708396004C5E1F /* DiffSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4BF61A21708396004C5E1F /* DiffSequence.swift */; };
1EB1AD2720BD5E22004D0450 /* NSAttributedString+Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EB1AD2620BD5E22004D0450 /* NSAttributedString+Diff.swift */; };
1EB1AD2920BD640B004D0450 /* NSAttributedString+DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EB1AD2820BD640B004D0450 /* NSAttributedString+DiffTests.swift */; };
OBJ_21 /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* Diff.swift */; };
Expand All @@ -48,7 +47,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1E4BF61A21708396004C5E1F /* DiffSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffSequence.swift; sourceTree = "<group>"; };
1E78630721C394C5006F4912 /* Sdifft.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Sdifft.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
1EB1AD2620BD5E22004D0450 /* NSAttributedString+Diff.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Diff.swift"; sourceTree = "<group>"; };
1EB1AD2820BD640B004D0450 /* NSAttributedString+DiffTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+DiffTests.swift"; sourceTree = "<group>"; };
OBJ_12 /* DiffTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -107,6 +106,7 @@
OBJ_5 = {
isa = PBXGroup;
children = (
1E78630721C394C5006F4912 /* Sdifft.playground */,
OBJ_6 /* Package.swift */,
OBJ_7 /* Sources */,
OBJ_10 /* Tests */,
Expand All @@ -126,7 +126,6 @@
isa = PBXGroup;
children = (
OBJ_9 /* Diff.swift */,
1E4BF61A21708396004C5E1F /* DiffSequence.swift */,
1EB1AD2620BD5E22004D0450 /* NSAttributedString+Diff.swift */,
);
name = Sdifft;
Expand Down Expand Up @@ -229,7 +228,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null;\nthen\nswiftlint\n#cd Teambition&&swiftlint\nelse\necho \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi";
shellScript = "if which swiftlint >/dev/null;\nthen\nswiftlint\nelse\necho \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */

Expand All @@ -238,7 +237,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 0;
files = (
1E4BF61B21708396004C5E1F /* DiffSequence.swift in Sources */,
1EB1AD2720BD5E22004D0450 /* NSAttributedString+Diff.swift in Sources */,
OBJ_21 /* Diff.swift in Sources */,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>classNames</key>
<dict>
<key>DiffTests</key>
<dict>
<key>testTime()</key>
<dict>
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
<dict>
<key>baselineAverage</key>
<real>0.36825</real>
<key>baselineIntegrationDisplayName</key>
<string>Local Baseline</string>
</dict>
</dict>
</dict>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>classNames</key>
<dict>
<key>DiffTests</key>
<dict>
<key>testTime()</key>
<dict>
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
<dict>
<key>baselineAverage</key>
<real>0.8</real>
<key>baselineIntegrationDisplayName</key>
<string>Local Baseline</string>
</dict>
</dict>
</dict>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>runDestinationsByUUID</key>
<dict>
<key>A8E95969-EF02-4FA2-9760-6D628059A4C2</key>
<dict>
<key>localComputer</key>
<dict>
<key>busSpeedInMHz</key>
<integer>400</integer>
<key>cpuCount</key>
<integer>1</integer>
<key>cpuKind</key>
<string>Intel Core i5</string>
<key>cpuSpeedInMHz</key>
<integer>2300</integer>
<key>logicalCPUCoresPerPackage</key>
<integer>8</integer>
<key>modelCode</key>
<string>MacBookPro15,2</string>
<key>physicalCPUCoresPerPackage</key>
<integer>4</integer>
<key>platformIdentifier</key>
<string>com.apple.platform.macosx</string>
</dict>
<key>targetArchitecture</key>
<string>x86_64</string>
<key>targetDevice</key>
<dict>
<key>modelCode</key>
<string>iPhone10,6</string>
<key>platformIdentifier</key>
<string>com.apple.platform.iphonesimulator</string>
</dict>
</dict>
<key>DCB9F5A5-E22D-4494-A0DC-4412307D88CA</key>
<dict>
<key>localComputer</key>
<dict>
<key>busSpeedInMHz</key>
<integer>400</integer>
<key>cpuCount</key>
<integer>1</integer>
<key>cpuKind</key>
<string>Intel Core i5</string>
<key>cpuSpeedInMHz</key>
<integer>2300</integer>
<key>logicalCPUCoresPerPackage</key>
<integer>8</integer>
<key>modelCode</key>
<string>MacBookPro15,2</string>
<key>physicalCPUCoresPerPackage</key>
<integer>4</integer>
<key>platformIdentifier</key>
<string>com.apple.platform.macosx</string>
</dict>
<key>targetArchitecture</key>
<string>x86_64</string>
<key>targetDevice</key>
<dict>
<key>modelCode</key>
<string>iPhone11,8</string>
<key>platformIdentifier</key>
<string>com.apple.platform.iphonesimulator</string>
</dict>
</dict>
</dict>
</dict>
</plist>
Loading

0 comments on commit 26f1a89

Please sign in to comment.