Files
QWERTYkez.OpenXmlProcessors/QWERTYkez.ExcelProcessor/NormalizedSet.cs
melekhin e373d4108a
All checks were successful
Publish NuGet packages / publish (push) Successful in 28s
many debugs
2026-06-19 15:06:40 +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>
internal class NormalizedSet : ISet<string>
{
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>
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();
}