Tester si une valeur est dans tableau [Résolu]

Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
- 3 mai 2008 à 16:46 - Dernière réponse :
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 4 mai 2008 à 19:11
Bonjour à tous,

J'ai un tableau d'entiers (dynamique ou statique)
et je voudrais tester si une valeur est comprise dans mon tableau
sans passer par une boucle.
j'aimerais bien un truc comme if Numb in [ qlqchose  ] then..

est-ce possible ?

merci par avance

cantador
Afficher la suite 

Votre réponse

23 réponses

Meilleure réponse
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 3 mai 2008 à 17:20
3
Merci
Salut Cantador,

J'ai une proposition assez performante avec MatchesMask().
Mais il te faudra écrire ton tableau sous forme de chaîne.

1 exemple :
procedure TForm1.Button1Click(Sender: TObject);
  var   Tablo : String;
begin
  Tablo := '12,34,56,78,90,100';
  if MatchesMask(Tablo,'*90*') then ShowMessage('90 est ds la chaîne') else ShowMessage('90 n''est pas ds la chaîne');
  if MatchesMask(Tablo,'*95*') then ShowMessage('95 est ds la chaîne') else ShowMessage('95 n''est pas ds la chaîne');
end;

Merci Caribensila 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 89 internautes ce mois-ci

Commenter la réponse de Caribensila
Meilleure réponse
Messages postés
2354
Date d'inscription
dimanche 5 octobre 2003
Dernière intervention
18 novembre 2010
- 3 mai 2008 à 18:06
3
Merci
Moi je veux idem que cantador mais avec des chars :]
S := 'Q';
if S in ['A'..'Z'] then showmessage('ok');

Merci JulioDelphi 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 89 internautes ce mois-ci

Commenter la réponse de JulioDelphi
Meilleure réponse
- 3 mai 2008 à 18:15
3
Merci
Salut,

Pour rechercher une valeur dans un tableau tu n'as pas d'autres choix que de le parcourir. Après il existe des fonctions/expressions ou tu n'écris par de boucle mais en réalité il y en a quand meme une qui a lieu :

1)La méthode de Julio ne fait pas intervenir de boucle dans son écriture mais la recherche induite en fait inévitablement appel.

2)La méthode de Cari aussi : elle utilise la dichotomie ce qui induit une recherche plus rapide. Mais il y a quand meme une boucle en interne.

Désolé Cantador mais cela me semble impossible : c'est comme chercher une clé dans 25 vases. La seule facon de savoir quel vase contient la clé est de tous les parcourir jusqu'a la recherche du trophée.

Je te conseil la méthode de Cari car elle est beaucoup plus rapide qu'une boucle classique ou la technique proposée par Julio. Cependant tu dois utiliser des strings (Sachant qu'un transtypage pour chaque valeur va faire chuter les performances de facon vertigineuse)

Merci Utilisateur anonyme 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 89 internautes ce mois-ci

Commenter la réponse de Utilisateur anonyme
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 3 mai 2008 à 18:29
0
Merci
Salut !

La technique utilisée par Julio ne fait pas appel à des boucles, mais elle est limitée à des types de 8 bits (Byte ou Char).
De plus, si tu fais "if S in ['A', 'C', 'F'..'I', 'O', 'Q', 'X'..'Z'] then", tu perds pas mal en perfs.
Cependant, ça reste quand même le plus rapide.

La méthode de Cari me semble la plus lente si le test est à effectuer avec des Integer.
Dans le cas de nombres, le mieux reste :
- de les trier une fois pour toutes (voir ma source sur QuickSort pour pas s'embêter avec le tri)
- d'utiliser ensuite une méthode dichotomique pour rechercher si le nombre est dans la liste ou pas.

Mais cette technique a aussi un désavantage si tu modifies souvent ton tableau.

En fait, tout dépend de tes structures de données !
Tu peux aussi utiliser un arbre (binaire ou non) si l'occasion s'y prête. Tu auras alors les coûts de ré-alignements mais suivant ce que tu fais, c'est plus rapide.
Commenter la réponse de florenth
Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
- 3 mai 2008 à 18:38
0
Merci
Merci à tous les trois
C'est vraiment sympa..
Je croyais qu'il existait du "prêt à cuire"..
Tant pis..

En fait, c'est de ma faute j'aurais du préciser que je souhaitais faire ce test de manière répétitive..

J'ai donc codé une petite fonction et voilà ce que çà donne :

procedure TForm1.cxButton8Click(Sender: TObject);
var
i, adf: integer;
TSelectF : array of integer;
TabATester : array[1..100] of integer;
 
function Numela(param: integer; var TAB: array of integer): boolean;
  var
    i: integer;
  begin
    Result := false;
    for i := 0 to high(TAB) do
      if param = TAB[i] then
        Result := true;
  end;
begin

adf := 0;
 Initialize(TSelectF );
 SetLength(TSelectF , 100);

        for i := 0 to high(TabATester ) do
          if not Numela(TabATester [i], TSelectF ) then
          begin
            TSelectF [adf] := TabATester [i];
            inc(adf);
          end;
 SetLength(TSELECTF, adf);

// etc etc etc..
end;

Si vous avez mieux..

cantador
Commenter la réponse de cs_cantador
Messages postés
2354
Date d'inscription
dimanche 5 octobre 2003
Dernière intervention
18 novembre 2010
- 3 mai 2008 à 18:38
0
Merci
Quelle taille fait le tableau ? Est il si grand pour ne pas vouloir faire une boucle dessus ?
Commenter la réponse de JulioDelphi
- 3 mai 2008 à 18:49
0
Merci
Salut

1)Je quote le code de Julio :

S := 'Q';
if S in ['A'..'Z'] then showmessage('ok');

Si je lis mot à mot ce code
S correspond à 'Q'
Si S est dans le tableau ['A'..'Z'] alors

Soit il y a pas de boucles d'écrits (Comme je le disais), Mais Flo va falloir m'expliquer comment ca fonctionne, s'il y a pas une boucle qui a lieu au niveau du ['A'..'Z'] d'une facon ou d'une autre (Par exemple elle pourrait apparaitre lors de la transformation du code en ASM).

2)"La méthode de Cari me semble la plus lente si le test est à effectuer avec des Integer".  D'accord mais là on parle de chaines caractères. Une fois trouvée non pas l'integer mais la chaine voulue, on transtype. Dans ces conditions la méthode de Julio risque d'etre lente comparée à celle de Cari dans ces conditions, en particulier si la taille du tableau est importante non ?

Je sens que cela va se terminer par un test de perfs
Commenter la réponse de Utilisateur anonyme
Messages postés
2354
Date d'inscription
dimanche 5 octobre 2003
Dernière intervention
18 novembre 2010
- 3 mai 2008 à 18:59
0
Merci
Nan mais j'ai fait dériver le sujet là :p
A la base on parle bien d'un tableau d'entier ^^ Moi j'ai mis mon grain de sel avec ça XD
Commenter la réponse de JulioDelphi
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 3 mai 2008 à 19:00
0
Merci
... Question perfs, je ne sais pas encore  

Mais l'utilisation d'un ensemble présente au moins deux inconvénients, à mon avis :
- le type de base ne peut avoir plus de 256 valeurs
- une même valeur ne peut pas apparaître deux fois. 
Commenter la réponse de Caribensila
- 3 mai 2008 à 19:04
0
Merci
C'est pas toi le coupable Julio, C'est Cari

Mais la double question m'interesse :
1)Flo affirme que ca fonctionne sans boucle meme au niveau du code compilé. Mon coté rationnel titille ma curiosité : comment on peut chercher sur le planc conceptuel une valeur dans un tableau sans parcourir d'une facon ou d'une autre ce dernier .
2)Si si on va faire des tests de perfs . Je vais me chercher des clopes et je me penche sur le sujet.
Commenter la réponse de Utilisateur anonyme
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 3 mai 2008 à 19:11
0
Merci
« sans parcourir d'une facon ou d'une autre ce dernier »

Ce qui est sûr, c'est que si la valeur cherchée s'y trouve, ça ira plus vite.

Surtout si elle est en 1ère position.   lol
Commenter la réponse de Caribensila
Messages postés
2354
Date d'inscription
dimanche 5 octobre 2003
Dernière intervention
18 novembre 2010
- 3 mai 2008 à 19:12
0
Merci
Peut etre Delphi compare une valeur hexa de mon caractère Q (valant 51) qui est donc compris entre 41 (le A) et 5A (le Z) ?
Commenter la réponse de JulioDelphi
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 3 mai 2008 à 19:45
0
Merci
Juste pour info : ['A'..'Z'] n'est pas un tableau
mais un ensemble

Extrait de l'aide de Delphi:
Constructeurs d'ensembles

Un constructeur d'ensemble désigne une valeur de type
ensemble. Par exemple,[5, 6, 7, 8]

désigne
l'ensemble dont les membres sont 5, 6, 7 et 8. Le constructeur
d'ensemble :[ 5..8 ]

désigne le
même ensemble.La syntaxe d'un constructeur d'ensemble
est :[ élément1, ..., élémentn ]où chaque élément est soit une expression désignant un scalaire ayant
le type de base de l'ensemble ou une paire de telles expressions avec deux
points (..) entre. Quand un élément est de la forme x..y, c'est un abrégé pour tous les scalaires compris
dans l'intervalle allant de x à y, bornes incluses ; mais si x est supérieur à y, alors
x..y ne désigne rien et
[x..y] est l'ensemble vide. Le constructeur d'ensemble [ ] désigne l'ensemble vide alors que [x] désigne l'ensemble dont le seul membre est la valeur
de x.Voici des exemples
de constructeurs d'ensembles :[red, green, MyColor]
[1, 5, 10..K mod 12, 23]
['A'..'Z', 'a'..'z', Chr(Digit + 48)]

Pour plus
d'informations sur les ensembles, voir <mshelp:link keywords="structuredtypes_common" namespace="ms-help://borland.bds4">Ensembles</mshelp:link>.
 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 3 mai 2008 à 20:19
0
Merci
Exact Julio !
Delphi effectue deux additions pour déterminer si la valeur se trouve dans le bon intervalle.
Dans le cas ou tu précises plusieurs intervalles comme [1..25, 50..99] alors il y a quatre additions, et ainsi de suite !
Mais finalement, pas de tableau ! Et c'est là l'avantage !

Bien sur, ce genre de code n'es optimisé qu'a la compilation, donc si ton ensemble E est inconnu à la compil, ça risque d'être plus dur pour Delphi d'optimiser, et il y a aura une boucle.
Commenter la réponse de florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 3 mai 2008 à 20:28
0
Merci
Groossse bétise de ma part !!
Dans tous les cas, il n'y a pas de boucles pour les ensembles, mais une opération bit-à-bit.

Dans le cas suivant, voici le code asm pour vérifier "if B in E then":
and ebx, $000000ff
bt [epb-$20],ebx
jnb +$0a

Ce qui est trèèès court et donc très rapide !
Pour info, voila le code de test :

type
TByteSet = set of Byte;

function GetEns: TByteSet;
begin
if Random > 0.5 then
Result := [1..25, 50..99]
else
Result := [1, 8, 9, 12, 48, 51, 78];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
E: TByteSet;
B: Byte;
begin
B := Trunc(Random * 256);
E := GetEns;
if B in E then
ShowMessage('ok');
end;

Alors ? Scotché le francky hein ?
(la boule est en fait dans les instructions du processeur, mais comme il s'agit d'instructions "de base" ça va super vite, ndlr)
Commenter la réponse de florenth
- 3 mai 2008 à 21:11
0
Merci
Alors ? Scotché le francky hein ? Non car comme tu l'a dis il y a bel et bien  une boucle qui a lieu .

Plus honettement le ' if B in E then' utilise une technique de détermination plus performante (comme l'est la méthode par dichotomie) qu'un simple listage, mais cela n'enlève rien à l'obligation d'une boucle (Comme je te disais il fallait bien quelque soit quelque part . Il s'avère qu'elle est dans les instructions du processeur).

On pourrait aussi penser à une autre technique qui consiste à lister le tableau (ou constructeur d'ensembles dans notre cas) des deux extremités à la fois une sorte de For To - For DownTo. Il est fort à parier que coder correctement on obtient de bien meilleur résultat qu'un simple listage et peut etre meme que par la méthode dichotomique.

Par contre effectivement méa culpa, la méthode de Julio doit etre plus rapide .
Commenter la réponse de Utilisateur anonyme
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 3 mai 2008 à 21:44
0
Merci
Pour que ton idée For To + For DownTo fonctionne, il faudrait threader l'application et avoir au moins un dual-core je pense.
Commenter la réponse de Caribensila
- 3 mai 2008 à 22:59
0
Merci
Dual Core je sais pas Cari mais threader l'application peut etre une bonne idée (Ca dépend du code  : je vais faire des tests tiens )

C'est pas possible il doit y avoir des mots qui sont bouffer par la TextBox
Commenter la réponse de Utilisateur anonyme
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
- 4 mai 2008 à 01:51
0
Merci
si c'est pour des tableaux d'entiers :

function ValueInArray(const aValue: integer; const aArray: array of integer; var aValueIndex: integer): boolean;
var
  n, L, H: integer;
begin
  result := false;
  L := Low(aArray);
  H := high(aArray);
  aValueIndex := L-1;
  for n := L to H do
  begin    result :aValue aArray[n];
    if result then
    begin
      aValueIndex := n;
      exit;
    end;
  end;
end;

...

en passant :

if N in [X] then

test si N est dans l'ENSEMBLE [X]

ensembles =/= tableaux

Commenter la réponse de f0xi
- 4 mai 2008 à 03:29
0
Merci
Oué mais pour tester si N est dans l'ENSEMBLE [X] faut bien qu'il regarde si chacun des éléments correspond à X ? Donc sans boucle pas possible.

Qui a dit que Francky il est tétu
Commenter la réponse de Utilisateur anonyme

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.