Implemented function to compute minimal delta of two texts
This commit is contained in:
parent
6bbc953309
commit
e3b6446c3b
108
lib/utility.dart
Normal file
108
lib/utility.dart
Normal file
@ -0,0 +1,108 @@
|
||||
class Word {
|
||||
final int start;
|
||||
final int end;
|
||||
final String text;
|
||||
|
||||
Word({required this.start, required this.end, required this.text});
|
||||
}
|
||||
|
||||
class WordDelta {
|
||||
Word? old;
|
||||
Word? modified;
|
||||
|
||||
WordDelta({this.old, this.modified});
|
||||
}
|
||||
|
||||
class TextDelta {
|
||||
final List<WordDelta> wordDeltas = [];
|
||||
}
|
||||
|
||||
class Utility {
|
||||
static List<Word> splitToWords(String text) {
|
||||
List<Word> words = [];
|
||||
String currentWord = "";
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
if (text[i] == " " ||
|
||||
text[i] == "\n" ||
|
||||
text[i] == "\r" ||
|
||||
text[i] == "\t") {
|
||||
if (currentWord.isNotEmpty) {
|
||||
words.add(
|
||||
Word(start: i - currentWord.length, end: i, text: currentWord));
|
||||
currentWord = "";
|
||||
}
|
||||
} else {
|
||||
currentWord += text[i];
|
||||
}
|
||||
}
|
||||
if (currentWord.isNotEmpty) {
|
||||
words.add(Word(
|
||||
start: text.length - currentWord.length,
|
||||
end: text.length,
|
||||
text: currentWord));
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
static List<TextDelta> compare(String oldText, String newText) {
|
||||
var oldWords = splitToWords(oldText);
|
||||
var newWords = splitToWords(newText);
|
||||
|
||||
int oldIndex = 0;
|
||||
int newIndex = 0;
|
||||
|
||||
List<TextDelta> textDeltas = [];
|
||||
while ((oldIndex < oldWords.length) && (newIndex < newWords.length)) {
|
||||
var oldWord = oldWords[oldIndex];
|
||||
var newWord = newWords[newIndex];
|
||||
if (oldWord.text == newWord.text) {
|
||||
oldIndex++;
|
||||
newIndex++;
|
||||
} else {
|
||||
var delta = TextDelta();
|
||||
delta.wordDeltas.add(WordDelta(old: oldWord, modified: newWord));
|
||||
textDeltas.add(delta);
|
||||
oldIndex++;
|
||||
newIndex++;
|
||||
|
||||
if (oldIndex < oldWords.length && newIndex < newWords.length) {
|
||||
var nextOldWord = oldWords[oldIndex];
|
||||
var newSubIndex = newIndex;
|
||||
var oldSubIndex = oldIndex;
|
||||
while (newSubIndex < newWords.length &&
|
||||
newWords[newSubIndex].text != nextOldWord.text) {
|
||||
WordDelta wordDelta =
|
||||
WordDelta(old: nextOldWord, modified: newWords[newSubIndex]);
|
||||
delta.wordDeltas.add(wordDelta);
|
||||
newSubIndex++;
|
||||
oldSubIndex++;
|
||||
}
|
||||
if (newIndex != newSubIndex) {
|
||||
newIndex = newSubIndex;
|
||||
oldIndex = oldSubIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newIndex < newWords.length) {
|
||||
var delta = TextDelta();
|
||||
while (newIndex < newWords.length) {
|
||||
delta.wordDeltas.add(WordDelta(modified: newWords[newIndex]));
|
||||
newIndex++;
|
||||
}
|
||||
textDeltas.add(delta);
|
||||
}
|
||||
|
||||
if (oldIndex < oldWords.length) {
|
||||
var delta = TextDelta();
|
||||
while (oldIndex < oldWords.length) {
|
||||
delta.wordDeltas.add(WordDelta(old: oldWords[oldIndex]));
|
||||
oldIndex++;
|
||||
}
|
||||
textDeltas.add(delta);
|
||||
}
|
||||
|
||||
return textDeltas;
|
||||
}
|
||||
}
|
||||
89
test/utlity_test.dart
Normal file
89
test/utlity_test.dart
Normal file
@ -0,0 +1,89 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fitlien_common/utility.dart';
|
||||
|
||||
void main() {
|
||||
test('Test splitToWords function 1', () {
|
||||
List<Word> words = Utility.splitToWords("This is a test sentence.");
|
||||
expect(words.length, 5);
|
||||
expect(words[0].text, "This");
|
||||
expect(words[1].text, "is");
|
||||
expect(words[2].text, "a");
|
||||
expect(words[3].text, "test");
|
||||
expect(words[4].text, "sentence.");
|
||||
});
|
||||
|
||||
test('Test splitToWords function 2', () {
|
||||
List<Word> words = Utility.splitToWords("This is a another sentence.");
|
||||
expect(words.length, 5);
|
||||
expect(words[0].text, "This");
|
||||
expect(words[1].text, "is");
|
||||
expect(words[2].text, "a");
|
||||
expect(words[3].text, "another");
|
||||
expect(words[4].text, "sentence.");
|
||||
});
|
||||
|
||||
test('Comparison test 1', () {
|
||||
var text1 = "ab bc cd";
|
||||
var text2 = "ab cb cd";
|
||||
var deltas = Utility.compare(text1, text2);
|
||||
expect(deltas.length, 1);
|
||||
expect(deltas[0].wordDeltas.length, 1);
|
||||
expect(deltas[0].wordDeltas[0].old!.text, "bc");
|
||||
expect(deltas[0].wordDeltas[0].modified!.text, "cb");
|
||||
});
|
||||
|
||||
test('Comparison test 2', () {
|
||||
var text1 = "ab bc cd";
|
||||
var text2 = "ab cb dc";
|
||||
var deltas = Utility.compare(text1, text2);
|
||||
expect(deltas.length, 1);
|
||||
expect(deltas[0].wordDeltas.length, 2);
|
||||
expect(deltas[0].wordDeltas[0].old!.text, "bc");
|
||||
expect(deltas[0].wordDeltas[0].modified!.text, "cb");
|
||||
expect(deltas[0].wordDeltas[1].old!.text, "cd");
|
||||
expect(deltas[0].wordDeltas[1].modified!.text, "dc");
|
||||
});
|
||||
|
||||
test('Comparison test 3', () {
|
||||
var text1 = "ab bc cd fe";
|
||||
var text2 = "ab cb cd ef";
|
||||
var deltas = Utility.compare(text1, text2);
|
||||
expect(deltas.length, 2);
|
||||
expect(deltas[0].wordDeltas.length, 1);
|
||||
expect(deltas[0].wordDeltas[0].old!.text, "bc");
|
||||
expect(deltas[0].wordDeltas[0].modified!.text, "cb");
|
||||
expect(deltas[1].wordDeltas.length, 1);
|
||||
expect(deltas[1].wordDeltas[0].old!.text, "fe");
|
||||
expect(deltas[1].wordDeltas[0].modified!.text, "ef");
|
||||
});
|
||||
|
||||
test('Comparison test 4', () {
|
||||
var text1 = "ab bc";
|
||||
var text2 = "ab cb cd ef";
|
||||
var deltas = Utility.compare(text1, text2);
|
||||
expect(deltas.length, 2);
|
||||
expect(deltas[0].wordDeltas.length, 1);
|
||||
expect(deltas[0].wordDeltas[0].old!.text, "bc");
|
||||
expect(deltas[0].wordDeltas[0].modified!.text, "cb");
|
||||
expect(deltas[1].wordDeltas.length, 2);
|
||||
expect(deltas[1].wordDeltas[0].old, null);
|
||||
expect(deltas[1].wordDeltas[0].modified!.text, "cd");
|
||||
expect(deltas[1].wordDeltas[1].old, null);
|
||||
expect(deltas[1].wordDeltas[1].modified!.text, "ef");
|
||||
});
|
||||
|
||||
test('Comparison test 5', () {
|
||||
var text1 = "ab bc cd ef";
|
||||
var text2 = "ab cb";
|
||||
var deltas = Utility.compare(text1, text2);
|
||||
expect(deltas.length, 2);
|
||||
expect(deltas[0].wordDeltas.length, 1);
|
||||
expect(deltas[0].wordDeltas[0].old!.text, "bc");
|
||||
expect(deltas[0].wordDeltas[0].modified!.text, "cb");
|
||||
expect(deltas[1].wordDeltas.length, 2);
|
||||
expect(deltas[1].wordDeltas[0].old!.text, "cd");
|
||||
expect(deltas[1].wordDeltas[0].modified, null);
|
||||
expect(deltas[1].wordDeltas[1].old!.text, "ef");
|
||||
expect(deltas[1].wordDeltas[1].modified, null);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user