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