Files
QWERTYkez.OpenXmlProcessors/QWERTYkez.ExcelProcessor/NormalizedSet.cs
2026-06-05 15:58:03 +07:00

135 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using System.Globalization;
namespace QWERTYkez.ExcelProcessor;
/// <summary>
/// Множество строк, которое автоматически приводит все добавляемые элементы
/// к верхнему регистру и удаляет диакритические знаки (например, 'ё' -> 'Е').
/// Реализует ISet&lt;string&gt;, поэтому может использоваться там, где ожидается этот интерфейс.
/// </summary>
public class NormalizedSet : ISet<string>
{
private readonly HashSet<string> _inner;
/// <summary>
/// Создаёт пустое нормализованное множество.
/// </summary>
public NormalizedSet()
{
_inner = [];
}
/// <summary>
/// Создаёт нормализованное множество, заполненное элементами из указанной коллекции.
/// </summary>
/// <param name="collection">Коллекция, элементы которой будут нормализованы и добавлены.</param>
public NormalizedSet(IEnumerable<string> collection)
{
_inner = [.. collection.Select(Normalize)];
}
/// <summary>
/// Нормализует строку: верхний регистр и удаление диакритики.
/// </summary>
private static string Normalize(string s)
{
if (string.IsNullOrEmpty(s))
return s;
var normalized = s.Normalize(NormalizationForm.FormD);
var sb = new StringBuilder();
foreach (char c in normalized)
{
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
sb.Append(c);
}
return sb.ToString().Normalize(NormalizationForm.FormC).ToUpperInvariant();
}
// ---------- Реализация ISet<string> ----------
public bool Add(string item) => _inner.Add(Normalize(item));
void ICollection<string>.Add(string item) => Add(item);
public void UnionWith(IEnumerable<string> other)
{
foreach (var item in other)
Add(item);
}
public void IntersectWith(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
_inner.IntersectWith(normalizedOther);
}
public void ExceptWith(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
_inner.ExceptWith(normalizedOther);
}
public void SymmetricExceptWith(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
_inner.SymmetricExceptWith(normalizedOther);
}
public bool IsSubsetOf(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.IsSubsetOf(normalizedOther);
}
public bool IsSupersetOf(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.IsSupersetOf(normalizedOther);
}
public bool IsProperSupersetOf(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.IsProperSupersetOf(normalizedOther);
}
public bool IsProperSubsetOf(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.IsProperSubsetOf(normalizedOther);
}
public bool Overlaps(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.Overlaps(normalizedOther);
}
public bool SetEquals(IEnumerable<string> other)
{
var normalizedOther = new HashSet<string>(other.Select(Normalize));
return _inner.SetEquals(normalizedOther);
}
// ---------- Реализация ICollection<string> ----------
public int Count => _inner.Count;
public bool IsReadOnly => false;
public void Clear() => _inner.Clear();
public bool Contains(string item) => _inner.Contains(Normalize(item));
public void CopyTo(string[] array, int arrayIndex) => _inner.CopyTo(array, arrayIndex);
public bool Remove(string item) => _inner.Remove(Normalize(item));
// ---------- Реализация IEnumerable<string> и IEnumerable ----------
public IEnumerator<string> GetEnumerator() => _inner.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}