Renamed Examples to Implementation
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Common.Distance;
|
||||
|
||||
public static class Calculator
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the levenshtein distance between two enumerables
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="reference"></param>
|
||||
/// <param name="hypothesis"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetDistance<T>(T reference, T? hypothesis)
|
||||
where T : IEnumerable
|
||||
{
|
||||
// Setup
|
||||
var refArr = reference.Cast<object>().ToArray();
|
||||
var hypArr = hypothesis?.Cast<object>().ToArray() ?? Array.Empty<object>();
|
||||
|
||||
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
|
||||
|
||||
// Fill matrix
|
||||
for (var x = 0; x <= refArr.Length; x++)
|
||||
{
|
||||
// Reference on X axis
|
||||
distance[x, 0] = x;
|
||||
}
|
||||
|
||||
for (var y = 0; y <= hypArr.Length; y++)
|
||||
{
|
||||
// Hypothesis on Y axis
|
||||
distance[0, y] = y;
|
||||
}
|
||||
|
||||
// Calculate distance
|
||||
for (var x = 0; x < refArr.Length; x++)
|
||||
{
|
||||
for (var y = 0; y < hypArr.Length; y++)
|
||||
{
|
||||
// BL Cost depends on whether the two elements are equal
|
||||
var cost = Equals(refArr[x], hypArr[y]) ? 0 : 1;
|
||||
|
||||
// Apply distance mask
|
||||
var c1 = distance[x, y] + cost; // Bottom left
|
||||
|
||||
var c2 = distance[x, y + 1] + 1; // Top left
|
||||
var c3 = distance[x + 1, y] + 1; // Bottom right
|
||||
|
||||
distance[x + 1, y + 1] = Min(c1, c2, c3); // Top right
|
||||
}
|
||||
}
|
||||
|
||||
return distance[refArr.Length, hypArr.Length];
|
||||
}
|
||||
|
||||
private static T Min<T>(params T[] values)
|
||||
{
|
||||
if (!values.Any())
|
||||
{
|
||||
throw new ArgumentException("Array cannot be empty", nameof(values));
|
||||
}
|
||||
|
||||
return values.Min()!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Common.Distance;
|
||||
|
||||
public readonly struct DistanceComparer<T> : IDistanceComparer<T>
|
||||
where T : IEnumerable
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public T Reference { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public T? Hypothesis { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public double Distance { get; }
|
||||
|
||||
public DistanceComparer(T reference) : this(reference, default)
|
||||
{
|
||||
}
|
||||
|
||||
public DistanceComparer(T reference, T? hypothesis)
|
||||
{
|
||||
Reference = reference;
|
||||
Hypothesis = hypothesis;
|
||||
|
||||
Distance = Calculator.GetDistance(Reference, Hypothesis);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var str = Hypothesis?.ToString();
|
||||
|
||||
if (Hypothesis is var hyp && Equals(hyp, Reference))
|
||||
{
|
||||
return str ?? string.Empty;
|
||||
}
|
||||
|
||||
return
|
||||
$"<strong style='color: orange;' title='REf: {Reference}, CER: {Distance}'>{str ?? "-"}</strong>";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Common.Distance;
|
||||
|
||||
public interface IDistanceComparer
|
||||
{
|
||||
/// <summary>
|
||||
/// The calculated absolute distance between
|
||||
/// <see cref="IDistanceComparer{T}.Reference"/> and
|
||||
/// <see cref="IDistanceComparer{T}.Hypothesis"/>
|
||||
/// </summary>
|
||||
public double Distance { get; }
|
||||
}
|
||||
|
||||
public interface IDistanceComparer<out T> : IDistanceComparer
|
||||
where T : IEnumerable
|
||||
{
|
||||
/// <summary>
|
||||
/// The comparison reference, meaning the "known to be correct" value
|
||||
/// </summary>
|
||||
public T Reference { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The value hypothesis, whose correctness is checked against <see cref="Reference"/>
|
||||
/// </summary>
|
||||
public T? Hypothesis { get; }
|
||||
}
|
||||
Reference in New Issue
Block a user