[filtre & string] Déduire d'après 2 chaines de caractères une liste de filtre

Résolu
rastamath69 Messages postés 45 Date d'inscription vendredi 9 avril 2004 Statut Membre Dernière intervention 9 novembre 2009 - 22 juin 2009 à 11:43
rastamath69 Messages postés 45 Date d'inscription vendredi 9 avril 2004 Statut Membre Dernière intervention 9 novembre 2009 - 1 juil. 2009 à 11:36
Bonjour,

Je vais vous résumer ma situation : j'utilise une méthode qui prend en entrée une chaine de caractères qui lui sert de filtre, par exemple "ab*". Elle ne prend qu'UN seul filtre en entrée et je n'ai pas le choix.
Mes utilisateurs m'ont demandé de pouvoir, via l'IHM, saisir 2 bornes par exemple "ax*" et "cbe*".

Je cherche donc un moyen simple d'isoler tous les filtres possibles compris entre ces 2 chaines.

Par exemple si on m'indique "ax* et "cbe*", j'aimerai être capable de me construire la liste suivante:
ax*
ay*
az*
b*
ca*
cba*
cbb*
cbc*
cbd*
cbe*

de sorte à pouvoir appeler la fameuse méthode ne prenant qu'un filtre en entrée.

Le seul moyen que je vois à l'heure actuelle est du découpage de chaine barbare et de l'analyse caractère par caractère. Or je ne trouve pas ça élégant, je souhaitais donc savoir si quelqu'un avait une solution plus propre!

Merci à vous!

Rastamath69, plus on travaille , plus on a des problèmes, donc plus on a de chances d'en résoudre! [8D]

1 réponse

rastamath69 Messages postés 45 Date d'inscription vendredi 9 avril 2004 Statut Membre Dernière intervention 9 novembre 2009 1
1 juil. 2009 à 11:36
Bonjour à tous,

J'ai vu que personne n'était arrivé à proposer une solution à ce problème (qui ma foi, était somme toute pas forcément simple...)
Aussi je vous dépose ici ma solution. Récursion peu élégante dans le parcours brute des caractères, je ne suis malheureusement pas arrivé à trouver mieux...

        /// <summary>
        /// Méthode qui construit une liste de filtre
        /// </summary>
        private List<String> PreparationListeFiltre(String borneInferieur, String borneSuperieur)
        {
            String tampon = String.Empty;
            List<String> listeRetour = new List<String>();

            try
            {
                borneInferieur = borneInferieur.ToUpper();
                borneSuperieur = borneSuperieur.ToUpper();

                //On met en place les * s'il n'y en a pas
                if (!borneInferieur.EndsWith("*"))
                    borneInferieur += "*";
                if ((borneSuperieur.CompareTo(String.Empty) 0) || (borneSuperieur.CompareTo("*") 0))
                    borneSuperieur = "Z";

                if (!borneSuperieur.EndsWith("*"))
                    borneSuperieur += "*";

                //Vérification de la cohérence des filtres
                if (!VerifChaine1PlusPetiteQueChaine2(borneInferieur, borneSuperieur))
                    throw new Exception("Premier filtre alphabétiquement moins grand que le deuxième.");

                tampon = borneInferieur;
                listeRetour.Add(tampon);
                while (tampon != borneSuperieur)
                {
                    tampon = Chaine_Suivante(tampon, borneSuperieur, false);
                    listeRetour.Add(tampon);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("Erreur lors de la préparation de la liste des filtre pour isoler les différents utilisateurs.", ex.Message);
                throw ex;
            }

            return listeRetour;
        }

        /// <summary>
        /// Retourne un booléen pour indiquer que chaine1 est bien placée avant chaine2 dans l'alphabet
        /// </summary>
        ///

        ///

        /// <returns></returns>
        private bool VerifChaine1PlusPetiteQueChaine2(String chaine1, String chaine2)
        {
            if (chaine1 == chaine2)
                return true;

            if (chaine1.Substring(0, 1) == chaine2.Substring(0, 1))
                return VerifChaine1PlusPetiteQueChaine2(chaine1.Substring(1, chaine1.Length - 1), chaine2.Substring(1, chaine2.Length - 1));
            else if (CharToInt(chaine1.Substring(0, 1)) > CharToInt(chaine2.Substring(0, 1)))
                return false;
            else
                return true;
        }

        /// <summary>
        /// Retourne une chaine qui correspond au filtre suivant attendu
        /// Cette méthode ne traite que des filtres ayant des majuscules. Les caractères autres que les 25 de l'alphabet ou que l'"*"
        /// ne sont pas tolérés.
        /// </summary>
        /// Plus petit paramètre attendu  = "A*"

        /// Filtre auquel il faudra s'arrêter

        /// Booléen indiquant si on a déjà trouvé une preuve de la supéritorité
        /// alphabétique de dernierFiltre sur filtre1

        /// <returns>Renvoie la chaine représentant le filtre suivant de filtre1 par rapport à dernierFiltre</returns>
        private string Chaine_Suivante(String filtre1, String dernierFiltre, bool plusGrandDejaTrouve)
        {
            if (filtre1 != String.Empty && dernierFiltre != String.Empty)
            {
                byte premiereLettreDernierFiltre = (byte)dernierFiltre.ToCharArray(0, 1)[0];
                byte premiereLettrePremierFiltre = (byte)filtre1.ToCharArray(0, 1)[0];

                //on élimine les premières lettres si elles sont égales et qu'on est toujours à égalité entre les 2 chaines
                if (Convert.ToInt32(premiereLettreDernierFiltre) == Convert.ToInt32(premiereLettrePremierFiltre) && !plusGrandDejaTrouve)
                {
                    return (filtre1.Substring(0, 1) + Chaine_Suivante(filtre1.Substring(1, filtre1.Length - 1), dernierFiltre.Substring(1, dernierFiltre.Length - 1), plusGrandDejaTrouve));
                }
                // si le caractère suivant du premier caractère du premier filtre, est égal au premier caractère du dernier
                //filtre et que ce nous ne sommes pas à la fin du dernier filtre
                else if (Convert.ToInt32(premiereLettreDernierFiltre) == (Convert.ToInt32(premiereLettrePremierFiltre) + 1) && !plusGrandDejaTrouve && !DerniereLettre(dernierFiltre))
                {
                    return (LettreSuivante(filtre1.Substring(0, 1)) + Chaine_Suivante(filtre1.Substring(1, filtre1.Length - 1), dernierFiltre.Substring(1, dernierFiltre.Length - 1), true));
                }
                else if (filtre1.Substring(0, 1) == "*") //cas spécifique où on doit réagrandir la chaine filtre1
                {
                    if (dernierFiltre.Substring(0, 1) == "A" && !DerniereLettre(dernierFiltre))
                    {
                        return "A" + Chaine_Suivante(filtre1, dernierFiltre.Substring(1, dernierFiltre.Length - 1), plusGrandDejaTrouve);
                    }
                    else
                    {
                        return "A*";
                    }
                }
                else
                {
                    //Si on arrive aux dernières lettres
                    if (DerniereLettreAvantZ(filtre1))
                        return LettreSuivante(filtre1.Substring(0, 1)) + "*";

                    if (dernierFiltre == "*")
                        return (filtre1.Substring(0, 1) + Chaine_Suivante(filtre1.Substring(1, filtre1.Length - 1), dernierFiltre, plusGrandDejaTrouve));

                    //si le premier caractère de Filtre1 est plus petit que celui de dernierFiltre
                    if ((CharToInt(filtre1.Substring(0, 1)) <= CharToInt(dernierFiltre.Substring(0, 1))) || plusGrandDejaTrouve)
                    {
                        return (filtre1.Substring(0, 1) + Chaine_Suivante(filtre1.Substring(1, filtre1.Length - 1), dernierFiltre.Substring(1, dernierFiltre.Length - 1), true));
                    }
                    else
                    {
                        //ERREUR : qui ne peut pas arriver si les chaines ont été vérifiées avant
                    }
                }
            }
            return String.Empty;
        }

        /// <summary>
        /// Indique pour une chaine qui se termine par *, et potentiellement des "Z" avant l'"*", s'il ne reste qu'une
        /// lettre avant.
        /// Exemple: pour EZZ* => VRAI
        ///          pour DZMZ* => FAUX
        /// </summary>
        ///

        /// <returns></returns>
        private bool DerniereLettreAvantZ(String filtre1)
        {
            if (filtre1.Substring(1, 1) == "*")
                return true;
            else if (filtre1.Substring(1, 1) != "Z")
                return false;
            else
                return DerniereLettreAvantZ(filtre1.Substring(1, filtre1.Length - 1));
        }

        /// <summary>
        /// Méthode prenant un Code Ascii en paramètre et retourne le caractère correspondant
        /// </summary>
        ///

        /// <returns></returns>
        private String IntToChar(Int32 codeAscii)
        {
            String resultat = String.Empty;
            byte b = (byte)codeAscii;
            resultat = ((char)b).ToString();
            return resultat;
        }

        /// <summary>
        /// Méthode prenant un caractère en entrée et qui retourne son code ascii
        /// </summary>
        ///

        /// <returns></returns>
        private Int32 CharToInt(String car)
        {
            Int32 resultat = 0;
            if (car != String.Empty)
            {
                char cara = car.ToCharArray()[0];
                resultat = (Int32)cara;
            }
            return resultat;
        }

        /// <summary>
        /// Retourne le caractère qui suit dans la table ASCII
        /// </summary>
        ///

        /// <returns></returns>
        private String LettreSuivante(String caractere)
        {
            String retour = String.Empty;
            if (caractere.Length == 1)
            {
                Int32 code = CharToInt(caractere);
                code++;
                retour = IntToChar(code);
            }
            else
            {
                retour = caractere;
            }

            return retour;
        }

        /// <summary>
        /// Définit, pour une chaine qui se termine par une *, si nous sommes à la dernière lettre
        /// </summary>
        ///

        /// <returns></returns>
        private bool DerniereLettre(String chaine)
        {
            return (chaine.Substring(1, 1) == "*");
        }

La méthode principale est "PréparationListeFiltre" qui prend en entrée les deux bornes entre lesquelles on souhaite établir la liste des filtres. Et elle vous retourne cette fameuse liste!!

En espérant, que cela puisse dépanner qq'un un de ces jours!

Bonne journée,

Rastamath69, plus on travaille , plus on a des problèmes, donc plus on a de chances d'en résoudre!
3
Rejoignez-nous