字符串集?

时间:2010-06-30 15:37:44

标签: delphi delphi-7

您熟悉此块:

Var
  mySet: Set Of Char;
  C: Char;
begin
  mySet := ['a', 'b', 'c'];
  If C In mySet Then ShowMessage('Exists');
end;

有没有办法申报Set Of STRING?或者是否有类似的代码我可以使用?这个块的重要部分是If C In mySet Then ShowMessage('Exists');我想在一组字符串中使用这样的东西 感谢。

7 个答案:

答案 0 :(得分:11)

使用位数组实现集合。所以不,你不能拥有一套'字符串'。请改用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; 

答案 1 :(得分:9)

你可以利用这个。

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;

答案 2 :(得分:5)

RTL System.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')

答案 3 :(得分:3)

很遗憾,但是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;

区分大小写。如果你需要不区分大小写的实现,你可以在put / look然后在set中使所有字符串小写(使用AnsiLowerCase函数)。

答案 4 :(得分:1)

Fabricio Araujo发布了原始问题的最佳答案。
但是如果你问这个问题,你也应该问自己
“我是否需要知道Str是否在此集合中?”。

关于“月份名称的允许缩写集中是否有MonthAbbr?”的问题
您的下一个问题是“那么,是哪个月份?”。

  • 您的代码应在一个函数调用中回答两个问题。 (例如,返回月份号,否则返回0)
  • 应为可读。立即向代码维护者明确您的意图
  • 应将允许的字符串存储在代码中的明显位置。
  • 应允许轻松修改(“添加'秋天'和'秋天',并在15分钟内将其带回给我。”)。
  • 对于集合的预期大小合理有效。
  • 如有可能,请使用标准库(VCL)。否则,请使用外部库。
  • 如果您的代码经常执行此类操作,请从实现中分离字符串,然后将实现放在一个位置,以便可以对其进行干净地更改。

因此您的代码可能显示为
case GetMonthNumber(Str) of 0: //Error: Str is not a Month Name or Abbreviation 1: //etc.

对于该实现,最简单的一般答案是在Delphi 7中使用排序的TStringList(因为标记了问题)。

答案 5 :(得分:0)

function MatchStr (常量AText:字符串;常量AValues:字符串数组):布尔值;超载;

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

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

答案 6 :(得分:0)

另一种选择是声明一个新的“String”类型并使用 RECORD HELPER 在其上实现“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.

它与赋值和比较中的 STRING 类型隐式兼容。它在“IN”运算符中隐式不区分大小写,并且通过扩展记录助手(使用 Equal/NotEqual/GreaterThan/LessThan/GreaterThanOrEqual/LessThanOrEqual 运算符到 STRING 和 TextString 类型),您可以制作完全不区分大小写的字符串类型。

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