Delphi 一组字符串??!!

Delphi 一组字符串??!!,delphi,delphi-7,Delphi,Delphi 7,您熟悉此块: Var mySet: Set Of Char; C: Char; begin mySet := ['a', 'b', 'c']; If C In mySet Then ShowMessage('Exists'); end; 是否有任何方法可以声明字符串集?或者有没有类似的代码可以替代?这个块的重要部分是如果mySet中有C,那么ShowMessage('Exists')我想对一组字符串使用类似这样的内容。 谢谢。集合是使用位数组实现的。因此,不能有“字符串集”。改

您熟悉此块:

Var
  mySet: Set Of Char;
  C: Char;
begin
  mySet := ['a', 'b', 'c'];
  If C In mySet Then ShowMessage('Exists');
end;
是否有任何方法可以声明字符串集?或者有没有类似的代码可以替代?这个块的重要部分是
如果mySet中有C,那么ShowMessage('Exists')我想对一组字符串使用类似这样的内容。

谢谢。

集合是使用位数组实现的。因此,不能有“字符串集”。改用TStringList,即:

var 
  mySet: TStringList;
  S: String;
begin 
  S := ...;
  mySet := TStringList.Create;
  try
    mySet.Add('a');
    mySet.Add('b');
    mySet.Add('c'); 
    if mySet.IndexOf(S) <> -1 Then ShowMessage('Exists');
  finally
    mySet.Free;
  end;
end; 
var
mySet:TStringList;
S:字符串;
开始
S:=。。。;
mySet:=TStringList.Create;
尝试
mySet.Add('a');
mySet.Add('b');
mySet.Add('c');
如果mySet.IndexOf(S)-1,则ShowMessage('Exists');
最后
mySet.Free;
结束;
结束;

您可以利用此功能

type 
  TAnyEnum = (aeVal1, aeVal2, aeVal3);
  TEnuns = set of TAnyEnum;
  TAnyMessages: array [TAnyEnum] of String;

const 
  MyMessages: TAnyMessages = ('Exists', 'Something else', 'WTF!?');

var
  MySet : TEnums;
begin
  MySet = [aeVal1, aeVal2];
  If aeVal1 in MySet then ShowMessage(MyMessages[aeVal1]);
end;

遗憾的是,Delphi甚至还没有非常基本的数据结构,比如集合。
“Fabricio Araujo”的建议在使用上非常有限——您必须知道所有可能的字符串,所以当您从某处读取它们时,它是无用的。在这样的“最短字符串集”中也不可能有超过256个项目。Remy Lebeau建议为此使用TStringList,但当你有大的电视机时,它是绝对没有效率的。在Delphi的现代版本中,可以使用TDictionary来保持任何东西的无序集,包括字符串:

procedure TForm6.FormCreate(Sender: TObject);
type
  TEmpty = record end;
var
  MySet: TDictionary<String, TEmpty>;
  Dummy: TEmpty;
begin
  MySet := TDictionary<String, TEmpty>.Create;
  try
    MySet.Add('Str1', Dummy);
    MySet.Add('Str2', Dummy);
    MySet.Add('Str3', Dummy);
    if MySet.TryGetValue('Str2', Dummy) then
      ShowMessage('Exists');;
  finally
    MySet.Free;
  end;
end;
过程TForm6.FormCreate(发送方:TObject);
类型
诱惑=记录结束;
变量
MySet:t词典;
虚拟:诱惑;
开始
MySet:=TDictionary.Create;
尝试
MySet.Add('Str1',Dummy);
MySet.Add('Str2',Dummy);
MySet.Add('Str3',Dummy);
如果MySet.TryGetValue('Str2',Dummy),则
ShowMessage('Exists');;
最后
MySet.Free;
结束;
结束;

它区分大小写。如果需要不区分大小写的实现,您可以在放置/查看之前将所有字符串小写(使用AnsiLowerCase函数)。

RTL
系统。StrUtils
单元为此提供了一种非常有趣的方法:

function MatchText(const AText: string; const AValues: array of string): Boolean; overload;
像这样使用它:

  if MatchText(sLanguages, ['fr-FR', 'en-GB', 'de-DE', 'it-IT', 'fr-CH', 'es-ES']) then
    Writeln('found')

法布里西奥·阿劳乔发布了原始问题的最佳答案。
但是如果你在问这个问题,你也应该问自己
“我是否只需要知道Str是否在此集合中?”

对于问题“MonthAbbr是否在允许的月份名称缩写中?”
很可能你的下一个问题是“那么,现在是哪个月?”

  • 您的代码应该在一个函数调用中回答这两个问题。(例如,返回月份编号为0)
  • 可读。让代码维护人员立即了解您的意图
  • 应将允许的字符串存储在代码中一个明显的地方
  • 应该允许简单的修改(“添加'Fall'和'秋'并在15分钟内将其带回给我”)
  • 对于集合的预期大小,具有合理的效率
  • 如果可能,请使用标准库(VCL)。否则,请使用外部库
  • 如果您的代码经常这样做,请将字符串与实现分离,并将实现放在一个位置,以便可以清楚地更改它
因此,您的代码可能会读取
case GetMonthNumber(Str)of
0://错误:Str不是月份名称或缩写
1://etc.


对于实现,最简单的一般答案是在Delphi7中使用排序的TStringList(问题被标记)。

函数MatchStr(const-AText:string;const-AValues:string数组):Boolean;超载

MatchStr使用区分大小写的比较来确定数组avalue中的任何字符串是否与AText指定的字符串匹配。如果数组中至少有一个字符串匹配,则返回true;如果所有字符串都不匹配,则返回false


对于不区分大小写的匹配
,请使用匹配文本例程。

另一个选项是声明新的“字符串”类型,并使用记录帮助器在其上实现“IN”运算符:

USES System.SysUtils, System.StrUtils;

TYPE
  TextString    = RECORD
                  PRIVATE
                    STR                 : STRING;
                  PUBLIC
                    CLASS OPERATOR      Implicit(CONST S : STRING) : TextString; INLINE;
                    CLASS OPERATOR      Implicit(CONST S : TextString) : STRING; INLINE;
                  END;
{ TextString }

CLASS OPERATOR TextString.Implicit(CONST S : STRING) : TextString;
  BEGIN
    Result.STR:=S
  END;

CLASS OPERATOR TextString.Implicit(CONST S : TextString) : STRING;
  BEGIN
    Result:=S.STR
  END;

TYPE
  TStringHelper = RECORD HELPER FOR TextString
                    CLASS OPERATOR In(CONST T : TextString ; CONST ARR : ARRAY OF STRING) : BOOLEAN;
                    FUNCTION       IsEmpty : BOOLEAN;
                  END;

{ TStringHelper }

CLASS OPERATOR TStringHelper.In(CONST T : TextString ; CONST ARR : ARRAY OF STRING) : BOOLEAN;
  BEGIN
    Result:=MatchText(T.STR,ARR)
  END;

FUNCTION TStringHelper.IsEmpty : BOOLEAN;
  BEGIN
    Result:=STR.IsEmpty
  END;

VAR
  S     : TextString;
  T     : STRING;

begin
  try
    REPEAT
      WRITE('Enter an animal name: '); READLN(T); S:=T;
      IF S.IsEmpty THEN EXIT;
      IF S IN ['Bird','Lion','Monkey'] THEN WRITELN('You got it!') ELSE WRITELN('Nope - Try Again...')
    UNTIL FALSE
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
它与赋值和比较中的字符串类型隐式兼容。它在“in”运算符中隐式不区分大小写,通过将记录帮助器(使用Equal/NotEqual/GreaterThan/LessThan/GreaterThanOrEqual/lessthanRequal运算符扩展为STRING和TextString类型)扩展为完全不区分大小写的字符串类型


缺点:您不能在VAR/OUT字符串参数中使用这种新类型,而且由于在比较中来回转换和大写,它比标准字符串类型慢一点。

如果您有很多字符串,最好使用排序列表并忽略重复项:mySet.sorted:=True;mySet.Duplicates:=dupsignores;大多数时候,我在.NET中使用字典是为了解决我的解决方案已经足够的情况。“因此,当你从某处阅读它们时,它是无用的”。不,没有用。不要使用数组常量,而是使用数组变量并从所需的源代码填充它。这将在编译时创建一个字符串为[0..5]的数组,并将其传递给函数。优点:这是一条线。在非常有限的情况下,这很好。例如,该字段中是否允许使用此字符串?缺点:如果你两次使用1-liner,你就产生了一个bug。代码的维护者可能会在一个实例中更改该集合,而错过另一个实例。此外,RTL正在使用字符串比较对该数组执行低效的线性搜索。Pos(俚语,'fr-fr,en-GB,de-de,it-it,fr-CH,es')>0会更快,但仍然不是一个好主意。@GuyGordon 1。MatchText函数的定义如下:函数MatchText(const-AText:string;const-AValues:string数组):布尔;->数组参数可以引用常量引用,如“const-cStrings:array of string=['fr-fr','en-GB','de-de','it-it','fr-CH','es']->数组现在只在一个位置被引用,即您想要的位置。2.您使用“Pos”的建议给出了错误的结果,因为它错误地接受了“fr”或“GB”之类的字符串。你说得对,谢谢。你必须把delimi