IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Construire une variable pas à pas à partir d'une liste [Débutant(e)]


Sujet :

Caml

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut [Résolu] Construire une variable pas à pas à partir d'une liste
    Disons que j'ai une liste de variables, que chaque variable peut être de plusieurs types, que seul le type 'Type1' m'interesse, et que le type 'Type1' contient un champ nommé 'val_int' qui est un entier.

    Je veux construire une chaîne de caractères contenant tous les entiers 'val_int' des 'Type1' de la liste.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    type 'a ref = { mutable contents: 'a }
     
      method create_string list =
        let string = { contents = "" } in
        List.iter (fun var ->
          match var with 
          | Type1(var_info) ->
              string.contents <- string.contents
                              ^ (fprintf_to_string "%i " var_info.val_int)
          | _ -> ()) list;
        string.contents
    Voici le code que j'ai pondu, il marche.

    Seulement dans ma précédente question, on m'a fait savoir qu'éviter d'utiliser des mutables, si possible, c'était mieux.

    Je voudrais donc savoir:
    - Est-ce que c'est un cas où il faut utiliser un mutable ? Si ce n'est pas le cas, comment faire pour s'en passer ?
    - Indépendamment du mutable, est-ce bien comme ca qu'il faut écrire ce genre de code ? Honnêtement, j'ai commencé par faire une boucle for ^^;; Quid de la vitesse, peut-on écrire ca de manière plus optimisée ?

  2. #2
    alex_pi
    Invité(e)
    Par défaut
    Déjà, pourquoi tu définis ton type ref à la main ?? Il y en a un de base dans caml, et il est pas si mal hein

    Ensuite, je pense que ce que tu veux faire, c'est un "List.fold_left". Et si ça te fait peur de concaténer des string, il faut un buffer.

  3. #3
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Points : 1 412
    Points
    1 412
    Par défaut
    Pour ma part, j'écrirais quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    let create_string list =
      let rec build = function
        | [] -> []
        | Type1 {val_int=i} :: l -> string_of_int i :: build l
        | _::l -> build l
      in String.concat " " (build list)
    Le résultat est presque le même (sauf que mon code ne met pas l'espace finale). Test sur une liste de 30000 éléments : ma fonction est 10 fois plus rapide que la tienne.

    Avec une bibliothèque plus fournie que celle de Caml, on peut tout faire sans récursion explicite (List.filter_map dans Batteries Included ; List.choose dans F#) et de façon plus élégante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let create_string list =
        let filter = function Type1 {val_int=i} -> Some (string_of_int i) | _ -> None in
        list |> List.filter_map filter |> String.concat " "

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Il faut bien promouvoir son propre travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.concat " " [? List : string_of_int i | Type1 {val_int=i} <- List : list ]

  5. #5
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut Et comme ça ?
    Bonjour !

    C'est mon premier message sur ce forum, et en plus on y parle de Caml, et en plus on y trouve des gens connus (trève de "en plus")

    Si j'ai bien compris le but c'est de prendre une liste de valeurs un peu siouxe et d'extraire les entiers sous forme de chaîne. Pourquoi pas ceci alors ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    let to_string =
      let buff = Buffer.create 16 in
      fun l ->
        Buffer.reset buff;
        List.iter (function
          | Type1 x -> Printf.bprintf buff "%i " x.val_int
          | _ -> ()
        ) l;
        Buffer.contents buff
    Fonction tail-rec sans surprise.

    Cordialement,
    Cacophrène

  6. #6
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Il faut bien promouvoir son propre travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.concat " " [? List : string_of_int i | Type1 {val_int=i} <- List : list ]
    Quelle extension de syntaxe ?

  7. #7
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Salut !

    Quelle extension de syntaxe ?
    Peut-être les list comprehension « implémentées-cachées » de camlp4, ou un truc dans le même genre, mais fait maison... Non ?

    Cordialement,
    Cacophrène

  8. #8
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Cacophrene Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    let to_string =
      let buff = Buffer.create 16 in
      fun l ->
        Buffer.reset buff;
        List.iter (function
          | Type1 x -> Printf.bprintf buff "%i " x.val_int
          | _ -> ()
        ) l;
        Buffer.contents buff
    Je sais que OCaml n'est pas "multithread", mais quel intéret y a-t-il à utiliser le même buffer pour tous les appels de la fonction ? On doit gagner un pouillème de miliseconde, et le jour où on peut lancer deux fois "to_string" en parallèle, on se retrouve avec un comportement aléatoire !

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Déjà, pourquoi tu définis ton type ref à la main ?? Il y en a un de base dans caml, et il est pas si mal hein
    Parce que j'ai vu ca dans un code source sur le net et que j'ai recopié en me disant "tient c'est pratique, bizarre que ca soit pas par default dans le language", ah bah si en fait...

    Citation Envoyé par bluestorm Voir le message
    Il faut bien promouvoir son propre travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.concat " " [? List : string_of_int i | Type1 {val_int=i} <- List : list ]
    Citation Envoyé par LLB Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let create_string list =
        let filter = function Type1 {val_int=i} -> Some (string_of_int i) | _ -> None in
        list |> List.filter_map filter |> String.concat " "
    Voilà deux solutions bien compactes je crois que je vais éviter de rajouter à mon programme d'autre dépendance que la librairie de parsing pour l'instant.

    @Cacophrene
    En fait, pour vous demander de l'aide, j'ai viré dans mon problème tout ce qui n'avait aucune pertinence avec mes questions, car en fait, ce n'est pas un int que je convertis en string, mais une structure complexe. La librairie de parsing fournis une fonction toute prête pour ca mais il n'est pas possible de connaître à l'avance la taille maximale retournée par cette dernière.

  10. #10
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Je sais que OCaml n'est pas "multithread", mais quel intéret y a-t-il à utiliser le même buffer pour tous les appels de la fonction ? On doit gagner un pouillème de miliseconde, et le jour où on peut lancer deux fois "to_string" en parallèle, on se retrouve avec un comportement aléatoire !
    Il va sans dire que cette fonction est à adapter en fonction de ce qu'on projette de faire avec par la suite... L'effet sur les performances n'est pas évident, j'en conviens (sauf peut-être pour de très longues listes, et encore, c'est à vérifier) . Disons que c'est plus une question d'habitude (honte à moi) qu'autre chose. Simplifions donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    let to_string l =
      let buff = Buffer.create 16 in
      List.iter (function Type1 x -> Printf.bprintf "%i " x.val_int | _ -> ()) l;
      Buffer.contents buff
    Puis comme ça je peux dire, moi aussi, que ma solution est compacte.

    Sinon c'est bien, ce fil de discussion, il propose plusieurs approches différentes pour arriver au même résultat. C'est stimulant et on le voit rarement sur d'autres forums. Je suis content d'être venu

    Cordialement,
    Cacophrène

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par LLB Voir le message
    Pour ma part, j'écrirais quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    let create_string list =
      let rec build = function
        | [] -> []
        | Type1 {val_int=i} :: l -> string_of_int i :: build l
        | _::l -> build l
      in String.concat " " (build list)
    Le résultat est presque le même (sauf que mon code ne met pas l'espace finale). Test sur une liste de 30000 éléments : ma fonction est 10 fois plus rapide que la tienne.
    Bon bah du coup j'ai opté pour cette solution là, merci bcp ^^

    Tant que j'y suis, j'ai une autre chaîne à construire, cette fois je recois 2 listes, et je dois concaténer tous les couples de var_int.

    En utilisant la même approche que ci-dessus, j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let create_string list1 list2 =
      let rec build1 = function
        | ([],var) -> []
        | (Type1 {val_int=i} :: l,var) -> string_of_int (i,var) :: build1 (l,var)
        | (_::l,var) -> build1 (l,var)
      in let rec build2 = function
        | [] -> []
        | Type1 {val_int=i} :: l -> String.concat " " (build1 (list1,i)) :: build2 l
        | _::l -> build2 l
      in String.concat " " (build2 list2)
    Est-ce que par hazard il y aurait encore plus rapide/élégant (avec juste les libs Ocaml standard) pour écrire cela ?

    En tout cas merci à tous pour les suggestions, cela m'en apprend beaucoup.

  12. #12
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Cacophrene Voir le message
    L'effet sur les performances n'est pas évident, j'en conviens (sauf peut-être pour de très longues listes, et encore, c'est à vérifier)
    En l'occurrence, c'est sur plein de petites listes que ta solution initiale pouvait présenter un intérêt. Mais je préfère largement la seconde

  13. #13
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Re !

    @bumbolol : Ceci peut-être (code non testé) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    open Printf
     
    let to_string2 l1 l2 =
      let buff = Buffer.create 16 in
      let to_string i = List.iter (function 
        | Type1 x -> bprintf buff "%i,%i " i x.val_int
        | _ -> ()
      ) l1 in List.iter (function Type1 x -> to_string x.val_int | _ -> ()) l2;
      Buffer.contents buff
    Attention : ce n'est peut-être pas ce que tu veux. Comme ton code utilise "string_of_int (i,var)" qui est incorrect (problème manifeste de typage) , j'ai essayé d'interpréter (avec plus ou moins de succès) d'après le texte.

    @alex_pi : Exact ! Où avais-je la tête... c'est sûr que pour observer un gain il faut une situation qui maximise la création de nouveaux buffers (petites listes), et non une autre où l'on en crée très peu (grandes listes). Vien bu

    @+
    Cacophrène

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.concat " " [? List : string_of_int i | Type1 {val_int=i} <- List : list ]
    Citation Envoyé par alex_pi Voir le message
    Quelle extension de syntaxe ?
    C'est pa_comprehension de Batteries ( lien vers la doc HTML des extensions ). C'est encore très jeune.

    Sinon tu peux effectivement utiliser Camlp4ListComprehension qui est en standard dans OCaml (camlp4o -parser Camlp4ListComprehension.cmo) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.concat " " [ string_of_int i | Type1 {val_int i} <- list ]
    Ça évite de spécifier les "List" mais en conterpartie ce n'est pas modulaire par rapport à la structure de donnée (pa_comprehension permet d'avoir facilement des Array ou whatever (Enum par défaut) en entrée ou en sortie).

    Un jour, une combinaison sublime avec le projet pa_do permettra (j'espère) de faire directement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List.[? string_of_int i | Type1 {val_int i} <- list ]

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par Cacophrene Voir le message
    Comme ton code utilise "string_of_int (i,var)" qui est incorrect (problème manifeste de typage) , j'ai essayé d'interpréter (avec plus ou moins de succès) d'après le texte.
    Oui string_of_int (i,var) ca veut pas dire grand chose, comme je l'ai dit plus haut, j'ai une jolie fonction qui va me faire une string à partir de pleins de paramètre, ce n'est pas spécialement pertinent de vous ennuyer avec ce genre de details, alors j'ai remplacé par le premier truc simple qui m'est passé par la tête.

    J'aurais plutôt du mettre string_of_whatever à la place ^^.

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par bumbolol Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let create_string list1 list2 =
      let rec build1 = function
        | ([],var) -> []
        | (Type1 {val_int=i} :: l,var) -> string_of_int_couple (i,var) :: build1 (l,var)
        | (_::l,var) -> build1 (l,var)
      in let rec build2 = function
        | [] -> []
        | Type1 {val_int=i} :: l -> String.concat " " (build1 (list1,i)) :: build2 l
        | _::l -> build2 l
      in String.concat " " (build2 list2)
    Aheum... je viens de me rendre compte que j'ai oublié un morceau important, je dois obtenir des listes de chaines de couple d'entier unique, en gros je ne dois concaténer que les éléments uniques de (build2 list2).

    Donc soit:

    - à la place de 'String.concat " " (build2 list2)' je fais 'let stripped_list = strip (build2 list2) in String.concat " " stripped_list' où trip est une fonction qui reste à écrire et qui prend une liste et retourne cette liste avec juste des elements uniques (pas bien dur à faire...).

    - dans 'build2' je remplace 'String.concat " " (build1 (list1,i)) :: build2 l' par quelque chose qui me permettent de n'ajouter 'String.concat " " (build1 (list1,i))' de manière unique, mais je vois pas du tout quoi ^^

  17. #17
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Salut !

    Je récapitule ce que j'ai compris :
    1. Tu as deux listes l1 et l2.
    2. On sélectionne tous les éléments uniques de la forme Type1 {val_int = i} dans l2
    3. On crée la chaîne de couples formés par i et tous les j des éléments de l1 qui sont de la forme Type1 {val_int = j}.

    Si c'est ça, voici une solution :

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    open Printf
     
    module IntSet = Set.Make (
      struct
        type t = int
        let compare = compare
      end
    )
     
    let to_string2 l1 l2 =
      let buff = Buffer.create 16 in
      let to_string i = List.iter (function 
        | Type1 x -> bprintf buff "%i,%i " i x.val_int
        | _ -> ()) l1 in
      let rec loop set = function
        | [] -> Buffer.contents buff
        | Type1 {val_int = i} :: l -> if IntSet.mem i set then loop set l
          else (to_string i; loop (IntSet.add i set) l)
        | _ :: l -> loop set l 
      in loop IntSet.empty l2

    Principe : Au fur et à mesure qu'elle progresse, la fonction loop stocke les entiers déjà passés en revue dans un set (une liste peut tout aussi bien faire l'affaire... selon les exigences de performance de la fonction mem). Si l'entier est unique, il est passé à la fonction to_string qui complète la liste.

    Et puis au besoin on peut même abstraire to_string2 pour choisir les fonctions et la valeur initiale de set, mais ça devient vraiment très lourd :

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    let to_string2 ~mem ~add ~ini l1 l2 =
      let buff = Buffer.create 16 in
      let to_string i = List.iter (function 
        | Type1 x -> bprintf buff "%i,%i " i x.val_int
        | _ -> ()) l1 in
      let rec loop set = function
        | [] -> Buffer.contents buff
        | Type1 {val_int = i} :: l -> if mem i set then loop set l
          else (to_string i; loop (add i set) l)
        | _ :: l -> loop set l
      in loop ini l2
     
    (* Exemple avec IntSet. *)
    let to_string2_set = to_string2 
      ~mem:IntSet.mem 
      ~add:IntSet.add 
      ~ini:IntSet.empty

    Très logiquement ça nous donne la signature suivante :

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    val to_string2 :
      mem:(int -> 'a -> bool) ->
      add:(int -> 'a -> 'a) -> 
      ini:'a -> t list -> t list -> string

    Ultime question que je me pose : les entiers de l1 doivent-ils aussi être uniques ? Si c'est le cas, il faut réécrire to_string dans mon code. Sinon, voici ce que ça donne sur un exemple bidon dans l'interpréteur :

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    # let x = [Type1 {val_int = 2}; Type1 {val_int = 2}; Type1 {val_int = 3}];;
    val x : t list =[Type1 {val_int = 2}; Type1 {val_int = 2}; Type1 {val_int = 3}]
    # to_string2_set x x ;;
    - : string = "2,2 2,2 2,3 3,2 3,2 3,3 "
    #

    Cordialement,
    Cacophrène

  18. #18
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par Cacophrene Voir le message
    Je récapitule ce que j'ai compris
    C'est vrai que c'est pas facile de décrire clairement ce que je veux faire. Le plus simple c'est p-e de mettre du code qui fait déjà ce que je veux (et que j'ai réussi à écrire grâce aux conseils déjà donnés ici), au moins pas d'ambiguïté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
        let rec build1 = function
          | ([],_) -> []
          | (Type1(h) :: q,val) -> ints_to_string (h.val_int,val) :: build1 (q,val)
          | (_::q,val) -> build1 (q,val)
        in let rec build2 = function
          | [] -> []
          | h :: q -> String.concat " " (build1 (list1,h.val_int)) :: build2 q
        in let rec strip = function
          | [] -> []
          | h :: q ->
            if List.exists (fun elt ->
            if (String.compare elt h) == 0 then true else false) q
            then strip q else h :: strip q
        in String.concat " " (strip (build2 list2))
    Si j'applique à ca ta technique de créer une liste des chaînes de couples déjà ajoutées à la liste retournée afin de vérifier avant d'en ajouter une nouvelle que celle-ci n'est pas déjà présente, on obtient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        let rec build1 = function
          | ([],_) -> []
          | (Type1(h) :: q,val) -> ints_to_string (h.val_int,val) :: build1 (q,val)
          | (_::q,val) -> build1 (q,val)
        in let rec build2 = function
          | ([],_) -> []
          | (h :: q,added) ->
            let new_string = String.concat " " (build1 (list1,h.val_int)) in
            if List.exists (fun elt ->
            if (String.compare elt new_string) == 0 then true else false) added
            then build2 (q,added) else new_string :: build2 (q,new_string :: added)
        in String.concat " " (build2 (list2,[]))
    Ca marche impec, merci beaucoup ^^.

    PS: Désolé de ne pas utiliser ta technique du Buffer, mais comme dis plus haut, les 2 ints en string, c'est juste pour l'exemple, en réalité j'utilise une fonction toute prête qui me génère une string à partir d'un champ d'une variable de type 'Type1' qui lui même est une structure possédant une quinzaine de champs et dont je ne peux prédire à l'avance la taille maximale de la chaîne retournée.

  19. #19
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Salut !

    Content de voir que ça marche

    @+
    Cacophrène

Discussions similaires

  1. Réponses: 2
    Dernier message: 04/06/2014, 15h18
  2. Réponses: 9
    Dernier message: 05/11/2008, 10h37
  3. Créer une variable d'environnement à partir d'une liste de fichier
    Par ddams dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 23/02/2007, 21h03
  4. Réponses: 1
    Dernier message: 17/01/2007, 22h52
  5. Réponses: 7
    Dernier message: 13/03/2006, 16h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo