Identify what has been added, removed and not changed by comparing two segments
$ dotnet add package SegmentComparerIdentify what has been added, removed, and unchanged by comparing two segments.
using System;
using System.Linq;
using SegmentComparer;
using SegmentComparer.Structure;
var comparer = new Comparer();
var original = "The quick brown fox";
var updated = "The quick red fox";
// Defaults: includeTags=true, tagVisualType=2 (FullTagText), semanticGrouping=true, comparisonType=0 (words)
var result = comparer.CompareSegment("seg-1", original, updated);
// Simple projection of results
var added = result.ComparisonUnits.Where(u => u.Type == ComparisonUnit.ComparisonType.New).Select(u => u.Text);
var removed = result.ComparisonUnits.Where(u => u.Type == ComparisonUnit.ComparisonType.Removed).Select(u => u.Text);
var same = result.ComparisonUnits.Where(u => u.Type == ComparisonUnit.ComparisonType.Identical).Select(u => u.Text);
Console.WriteLine("Added: " + string.Join(", ", added));
Console.WriteLine("Removed: " + string.Join(", ", removed));
Console.WriteLine("Unchanged: " + string.Join(", ", same));
// Edit distance
int relative;
int distance = comparer.GetSegmentEditDistance(original, updated, out relative, includeTags: true);
Console.WriteLine($"Edit distance: {distance} of {relative}");
Markdown-safe (renders everywhere; strike-through for removed, plain text for added/unchanged):
HTML-styled (for environments that allow inline styles; added=blue, removed=red strike, identical=black):
Note: nuget.org sanitizes styles, so the HTML colors may not render there. The Markdown-safe example will still show the strike-through.
using System;
using System.Linq;
using System.Net;
using System.Text;
using SegmentComparer;
using SegmentComparer.Structure;
// 1) Compare
var comparer = new Comparer();
var original = "The quick brown fox";
var updated = "The quick red fox";
var result = comparer.CompareSegment("seg-1", original, updated);
// 2) Build Markdown-safe text (strike for removed, plain for others)
static string BuildMarkdown(ComparisonResult result)
{
var sb = new StringBuilder();
foreach (var u in result.ComparisonUnits)
{
var text = u.Text; // already plain text at this point
switch (u.Type)
{
case ComparisonUnit.ComparisonType.Removed:
sb.Append("~~").Append(text).Append("~~");
break;
default:
sb.Append(text);
break;
}
}
return sb.ToString();
}
// 3) Build HTML with colors (blue added, red strike removed, black identical)
static string BuildHtmlInline(ComparisonResult result)
{
string StyleFor(ComparisonUnit.ComparisonType t) => t switch
{
ComparisonUnit.ComparisonType.New => "color:#1976d2;",
ComparisonUnit.ComparisonType.Removed => "color:#d32f2f;text-decoration:line-through;text-decoration-thickness:2px;text-decoration-color:#d32f2f;",
_ => "color:#000;"
};
var sb = new StringBuilder();
sb.Append("<div class=\"diff\">");
foreach (var u in result.ComparisonUnits)
{
var text = WebUtility.HtmlEncode(u.Text);
sb.Append("<span style=\"").Append(StyleFor(u.Type)).Append("\">")
.Append(text)
.Append("</span>");
}
sb.Append("</div>");
return sb.ToString();
}
// Examples
var md = BuildMarkdown(result);
var html = BuildHtmlInline(result);
Console.WriteLine("Markdown output:");
Console.WriteLine(md);
Console.WriteLine("\nHTML output:");
Console.WriteLine(html);
If you need character-level comparison, call CompareSegment with comparisonType: 1.
AB testing icons created by Bharat Icons — Flaticon