66 lines
2.3 KiB
C#
66 lines
2.3 KiB
C#
using System.Text.RegularExpressions;
|
||
|
||
namespace PlotLine.Services;
|
||
|
||
public static class StoryIntelligenceEntityTextNormaliser
|
||
{
|
||
private static readonly Regex Whitespace = new(@"\s+", RegexOptions.Compiled);
|
||
private static readonly Regex TitleFullStops = new(@"\b(Mr|Mrs|Ms|Miss|Dr|Prof|Rev|Revd)\.", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||
private static readonly Regex NonKeyCharacters = new(@"[^\p{L}\p{N}']+", RegexOptions.Compiled);
|
||
|
||
public static string Clean(string? value)
|
||
=> Whitespace.Replace((value ?? string.Empty).Replace('’', '\''), " ").Trim();
|
||
|
||
public static string CleanName(string? value)
|
||
=> Clean(value).Trim(' ', '.', ',', ';', ':', '!', '?', '"', '\'');
|
||
|
||
public static string StripLeadingArticle(string value)
|
||
{
|
||
var clean = Clean(value);
|
||
return clean.StartsWith("the ", StringComparison.OrdinalIgnoreCase)
|
||
? clean[4..]
|
||
: clean.StartsWith("a ", StringComparison.OrdinalIgnoreCase)
|
||
? clean[2..]
|
||
: clean.StartsWith("an ", StringComparison.OrdinalIgnoreCase)
|
||
? clean[3..]
|
||
: clean;
|
||
}
|
||
|
||
public static string SafeKey(string? value)
|
||
{
|
||
var clean = TitleFullStops.Replace(Clean(value), "$1");
|
||
clean = NonKeyCharacters.Replace(clean, " ");
|
||
clean = Whitespace.Replace(clean, " ").Trim().ToLowerInvariant();
|
||
return clean;
|
||
}
|
||
|
||
public static string SingulariseSafeFinalWord(string value, IReadOnlySet<string> singularisableWords)
|
||
{
|
||
var words = SafeKey(value).Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList();
|
||
if (words.Count == 0)
|
||
{
|
||
return string.Empty;
|
||
}
|
||
|
||
var last = words[^1];
|
||
if (last.EndsWith("ies", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
var singular = $"{last[..^3]}y";
|
||
if (singularisableWords.Contains(singular))
|
||
{
|
||
words[^1] = singular;
|
||
}
|
||
}
|
||
else if (last.EndsWith('s') && last.Length > 3)
|
||
{
|
||
var singular = last[..^1];
|
||
if (singularisableWords.Contains(singular))
|
||
{
|
||
words[^1] = singular;
|
||
}
|
||
}
|
||
|
||
return string.Join(' ', words);
|
||
}
|
||
}
|