7
votes

Ensemble de chaîne ?? !!

Vous connaissez ce bloc: xxx

existe-t-il un moyen de déclarer jeu de chaîne ? Ou y a-t-il un code similaire que je peux utiliser à la place? La partie importante de ce bloc est si c en mySet puis showMessage ("existe"); Je veux utiliser quelque chose comme ceci sur un ensemble de ficelles.
Merci.


0 commentaires

7 Réponses :


12
votes

Les ensembles sont implémentés à l'aide de tableaux de bits. Donc non, vous ne pouvez pas avoir un «jeu de chaîne». Utilisez une TStringList à la place, c'est-à-dire:

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 commentaires

Si vous avez beaucoup de chaînes, il pourrait être préférable d'utiliser la liste triée et d'ignorer les doublons: myset.sorted: = vrai; myset.duplicat: = Dupignores;



8
votes

Vous pouvez utiliser ceci.

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;


3 commentaires

Pour répondre correctement à la question, le point d'entrée doit être une chaîne et non un type énuméré. -> la question n'est pas respectée


@ Didiercabalé mais un ensemble Delphi doit être basé sur un type ordinal . Les chaînes ne sont pas des types ordinaux. Plus vous pouvez obtenir un ensemble de chaînes, c'est ça.


@Fabricioaraujo, cela dépend de l'endroit où vous vous concentrez sur: s'il s'agit d'utiliser ensemble de , je conviens que c'est le plus proche. Mais cela ne répond pas à la question fondamentale qui est comment savoir si une chaîne spécifique est dans un ensemble de chaîne , et dans ce cas, vous ne pouvez pas utiliser la construction de Pascal "Set de"



3
votes

C'est honte, mais Delphi n'a toujours pas encore de structures de données très élémentaires, comme des ensembles. Suggestion de "Fabricio Araujo" est très limitée dans l'usage - vous devez connaître toutes les chaînes possibles, il est donc inutile de les lire de quelque part. Il est également impossible d'avoir plus de 256 articles dans un tel "ensemble de chaînes la plus alternatif". Remy Lebeau a suggéré d'utiliser Tstringlist à cette fin, mais il est absolument inefficace lorsque vous avez de grands ensembles. Dans les versions modernes de Delphi, il est possible d'utiliser TDictionary pour garder un ensemble non ordonné de n'importe quoi, y compris des chaînes: xxx

il est sensible à la casse. Si vous avez besoin d'une mise en oeuvre insensible de cas, vous pouvez effectuer toutes les chaînes mises en couches avant de mettre / regarder ensuite dans le jeu (utilisez une fonction ansilowercase pour cela).


2 commentaires

La plupart du temps, j'utilise un dictionnaire dans .net est pour les cas où ma solution suffirait.


"Donc, il est inutile lorsque vous les lisez de quelque part". Non, n'est pas inutile. Au lieu d'utiliser une constante de réseau, utilisez une matrice variable et remplissez-la de la source souhaitée.



9
votes

Le système RTL System.strutils Unité fournit une méthode très intéressante pour cela: xxx

l'utiliser comme ceci: xxx


3 commentaires

Cela crée un tableau de [0..5] de la chaîne à la compilation et la transmet à la fonction. Avantages: c'est 1 ligne. C'est bien dans des situations très limitées. PAR EXEMPLE. Cette chaîne est-elle autorisée dans ce champ? Inconvénients: Si vous utilisez ce double doublure, vous avez induit un bug. Le responsable de votre code peut changer cela dans une seule instance et manquer l'autre. En outre, la RTL effectue une recherche linéaire inefficace de ce réseau à l'aide de la chaîne Comparer. POS (Slangues, 'FR-FR, EN-GB, DE-DE, IT-IT, FR-CH, ES-ES')> 0 serait plus rapide - et toujours pas une bonne idée.


@Guygordon 1. La fonction MatchText est définie comme suit: Fonction Matchtext (const Atext: chaîne; const Avalues: tableau de chaîne): Boolean; -> L'argument de tableau peut faire référence à une référence de const, comme "Const Cstrings: tableau de chaîne = ['FR-FR', 'EN-GB', 'DE-DE', 'IT-IT', 'FR-CH ',' es-es '] ". -> Le tableau est maintenant référencé dans un seul endroit, c'est-à-dire ce que vous vouliez. 2. Votre proposition d'utilisation du "POS" donne un problème incorrect, car il accepte à tort des cordes comme "FR" ou "GB".


Oups. Tu as raison, merci. Vous devez mettre des délimiteurs autour des substrings et autour de la chaîne de recherche. Et c'est sensible à la casse. Comme je l'ai dit, pas une bonne idée.



1
votes

Fabricio Araujo a posté la meilleure réponse à la question initiale.
Mais si vous posez cette question, vous devriez aussi vous demander
"Est-ce que je seul doit savoir si STR est dans cet ensemble?".

pour la question "est Montmabbr dans l'ensemble des abréviations autorisées des noms de mois?"
Les chances sont votre prochaine question est "bien alors, quel mois est ça?".

  • Votre code devrait répondre aux deux questions dans un appel de fonction. (E.G. Numéro de mois de retour 0)
  • devrait être lisible . Faites votre Intention IMEDIVELY CLAIRE AU MAINTENANT DE CODE.
  • doit stocker les chaînes autorisées dans un seul endroit évident de code.
  • devrait permettre une révision facile ("Ajouter" Automne "et" Automne "et me ramener cela dans 15 min.").
  • être raisonnablement efficace pour la taille attendue de l'ensemble.
  • Utilisez la bibliothèque standard (VCL) si possible. Sinon utilise une bibliothèque externe.
  • Si votre code fait ce type de chose souvent, séparez les cordes de la mise en œuvre et mettez la mise en œuvre au même endroit afin qu'elle puisse être modifiée proprement.

    Votre code pourrait donc lire
    Case GetMonThNumber (STR) de 0: // Erreur: STR n'est pas un nom de mois ou une abréviation 1: // etc.

    Pour la mise en œuvre, la réponse générale la plus simple consiste à utiliser une TStringList Trié dans Delphi 7 (comme la question est étiquetée).


0 commentaires

0
votes

fonction matchstr (const Atext: chaîne; const Avalues: tableau de chaîne): Boolean; surcharge;

Matchstr détermine si l'une des chaînes de la matrice avalue correspond à la chaîne spécifiée par ATTEXT à l'aide d'une comparaison Sensible>. Il revient vrai si au moins une des chaînes de la correspondance de la matrice, ou FALSE si aucune des chaînes correspondent.

pour une correspondance insensible à la case , utilisez la routine matchtext .


0 commentaires

1
votes

Une autre option consiste à déclarer une nouvelle "chaîne" et à utiliser une aide d'enregistrement pour implémenter l'opérateur "IN" sur celui-ci:

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.


0 commentaires