Оператор IN в Pascal традиционно используется для проверки принадлежности элемента к множеству (set). Однако многие разработчики хотели бы расширить его функциональность, например, для работы со строками и массивами. В этой статье мы рассмотрим способы перегрузки оператора IN в Delphi и альтернативные решения.
Проблема перегрузки оператора IN
Исходная задача проста: проверить, содержится ли строка в массиве строк, используя синтаксис оператора IN:
var hey: String;
begin
hey := 'one';
if hey in ['one', 'two'] then Exit;
К сожалению, стандартный Pascal не поддерживает такой синтаксис для строк.
Решение 1: Использование TStringArray
Первый рабочий вариант предполагает создание вспомогательной функции Group:
function Group(const Ar: array of String): TStringArray;
var
i: Integer;
begin
SetLength(Result, High(Ar)+1);
for i := 0 to High(Ar) do
Result[i] := Ar[i];
end;
operator in (A: String; B: TStringArray): Boolean;
var
i: Integer;
begin
for i := 0 to Length(B)-1 do
if B[i] = A then
Exit(True);
Result := False;
end;
Использование:
if hey in Group(['one', 'two']) then
// Действие
Решение 2: Прямая перегрузка для массива строк
Более элегантное решение предложено пользователем egsuh:
operator in (a: string; b: array of string) : boolean;
implementation
operator in(a: string; b: array of string): boolean;
var
c: string;
begin
Result := false;
for c in b do
if a = c then
Exit(true);
end;
Использование:
showmessage(BoolToStr('this' in ['this', 'that'], true));
Это решение более лаконично и не требует дополнительных преобразований.
Альтернативные подходы
Использование функций из модуля StrUtils
Как предложил cdbc, можно использовать IndexStr или IndexText:
var hey: String;
begin
hey := 'one';
case IndexText(hey, ['one','two','three']) of
0: Exit; // 'one'
1: Caption := 'Two';
2: ShowMessage('Three');
end;
Создание собственного класса-обертки
Для более сложных сценариев можно создать специальный класс:
type
TStringChecker = class
private
FValues: TStringArray;
public
constructor Create(const AValues: array of string);
function Contains(const AValue: string): Boolean;
end;
constructor TStringChecker.Create(const AValues: array of string);
var
i: Integer;
begin
SetLength(FValues, Length(AValues));
for i := 0 to High(AValues) do
FValues[i] := AValues[i];
end;
function TStringChecker.Contains(const AValue: string): Boolean;
var
s: string;
begin
Result := False;
for s in FValues do
if s = AValue then
Exit(True);
end;
Использование:
var
Checker: TStringChecker;
begin
Checker := TStringChecker.Create(['one', 'two', 'three']);
try
if Checker.Contains('one') then
ShowMessage('Found!');
finally
Checker.Free;
end;
end;
Производительность решений
При выборе решения стоит учитывать производительность:
Перегрузка оператора IN с array of string - наиболее быстрый вариант
Использование TStringArray с функцией Group - дополнительное преобразование массива
Класс-обертка - наибольшие накладные расходы, но больше гибкости
Заключение
Перегрузка оператора IN в Delphi возможна и может сделать код более читаемым. Наиболее элегантным решением является прямая перегрузка для array of string. Однако в некоторых случаях стандартные функции из StrUtils или специализированные классы могут оказаться более подходящими.
Выбор конкретного решения зависит от требований проекта, частоты использования и личных предпочтений разработчика.
В статье рассматриваются способы перегрузки оператора IN в Delphi для работы со строками и массивами, а также альтернативные решения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.