Supprimer les mêmes valeurs d'un tableau

heliohelio Membre

Bonjour,


Serait-il possible de m'expliquer le code suivant, surtout l'entête de la fonction.


Ce code permet de supprimer les mêmes valeurs d'un tableau.



func uniq<S : SequenceType, T : Hashable where S.Generator.Element == T>(source: S) -> [T] {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}

let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]


Merci.


 


Réponses

  • DrakenDraken Membre
    mai 2016 modifié #2

    Euh .. je comprend le principe de la routine, mais l'entête est delà  de ma compréhension. C'est du code générique permettant de travailler avec des tableaux contenant n'importe quel type d'objet.


     


    Pour le reste c'est simple.


    On crée un tableau vide buffer d'objet de type T (le type du tableau générique).


    Et added un Set d'objets T. C'est à  dire une collection ne pouvant contenir que des objects uniques.


     


    Ensuite on parcourt la liste des objets d'origine pour la comparer avec la collection. Si un objet n'est pas présent c'est la première fois que l'on le rencontre. On l'archive alors dans la collection et on l'ajoute au tableau buffet.


     


    A la fin, on retourne le tableau buffer, avec le type générique T.

  • PyrohPyroh Membre
    mai 2016 modifié #3

    L'entête c'est long et ça parait compliqué mais c'est simple. 


     


    Une fonction de type function<x> est une fonction générique. C'est à  dire qu'on va connaà®tre les types manipulés à  l'exécution.


    On va la décomposer :


     


     - S : SequenceType → On définit un alias S pour un type qui sera donné en entrée (ici source: S). Tout ce qu'on dit c'est qu'on ne sait pas ce que sera le type de S mais on sait qu'il répondra au protocol SequenceType. 


     - T : Hashable where S.Generator.Element == T → Ici encore on définit un alias (T en l'occurence). Il sert à  spécifier la valeur de retour donc on dit juste "tu renvoie un tableau d'objets de type T". On sait de ces objets qu'ils répondent au protocol Hashable (T : Hashable) mais aussi que ce type T est le type des objets contenu dans la source d'alias S (S.Generator.Element == T).


     


    Grosso modo ça veut dire que ta function pour fonctionner doit recevoir une sequence (Array, Set, Slice, etc...) dont les objets répondent au protocol Hashable et qu'elle te renverra alors un tableau contenant des objets du même type que ceux de la séquence passée en entrée. 


     


    Je te conseille d'aller jeter un oeil sur les docs de SequenceType et Hashable pour mieux comprendre.


  • DrakenDraken Membre

    Merci prof.


  • Est-ce que setWithArray de NSSet ne ferait pas le travail puisqu'un NSSet ne contient qu'une occurence d'un objet ?

  • CéroceCéroce Membre, Modérateur
    mai 2016 modifié #6

    Est-ce que setWithArray de NSSet ne ferait pas le travail puisqu'un NSSet ne contient qu'une occurence d'un objet ?

    Si.
    L'inconvénient est qu'un NSSet n'étant pas ordonné, l'ordre initial sera perdu. Nous ignorons ici si c'est un problème ou non.

    D'autre part, autant penser à  la manière de Swift dès à  présent. Les jours de Foundation dans Swift sont comptés: je ne retrouve plus l'annonce, mais cette framework va être réécrite pour faire de Swift un vrai langage multi-plateforme.

    Ma question serait plutôt: peut-on écrire ce code d'une manière fonctionnelle ?
  • Joanna CarterJoanna Carter Membre, Modérateur

    let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

    let uniqueVals = NSOrderedSet(array: vals)
  • DrakenDraken Membre

    Magnifique de simplicité !

  • PyrohPyroh Membre



    let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

    let uniqueVals = NSOrderedSet(array: vals)



     


    Ouais mais c'est pas Swifty et faut caster en plus...


    Je propose ça :



    func uniq<S: SequenceType, T: Hashable where T: Comparable, S.Generator.Element == T>(source: S) -> [T] {
    return [T](Set<T>(source)).sort(<)
    }
  • DrakenDraken Membre
    mai 2016 modifié #10

    C'est moins lisible par un noob. Il n'y a pas moyen d'écrire la même chose en une seule ligne, sans passer par les opérateurs génériques ?


  • sujet intéressant en tous les cas. Y'à  plus qu'a tester les performances des différents solutions ;-)


  • Joanna CarterJoanna Carter Membre, Modérateur

    Ouais mais c'est pas Swifty et faut caster en plus...




    C'est pas un cast, c'est un des constructeurs de NSOrderedSet
  • colas_colas_ Membre
    mai 2016 modifié #13

    Hello,


    J'ai commis ça (ça doit être la deuxième fois que j'écris un truc en Swift ;-)

    C'est une solution fonctionnelle je pense @Céroce.


    Pour le coup, j'ai ouvert un playground pour la première (mon ordi n'a pas apprécié et au bout de 10 minutes, Xcode ne répondait plus et le Finder n'était pas content non plus : reboot)


     



    func uniq<S:SequenceType, T:Hashable where S.SubSequence == S, S.Generator.Element == T> (source: S) -> [T]
    {
    let generator = source.generate()
    let firstElement = source.generate().next()

    if (firstElement == nil)
    {
    return []
    }

    let subSource = source.dropFirst()
    let uniqSubSource = uniq(subSource)

    if (subSource.contains(firstElement))
    {
    return uniqSubSource
    }
    else
    {
    return [firstElement] + uniqSubSource
    }
    }



    Le compilateur n'est pas content du tout... Si vous avez des pistes et explications...


    ça promet d'être sympa Swift...


  • PyrohPyroh Membre

    C'est pas un cast, c'est un des constructeurs de NSOrderedSet



    Sur ce point on est d'accord mais comme il veut un [Int] il va falloir caster quand même.
  • Joanna CarterJoanna Carter Membre, Modérateur


    Sur ce point on est d'accord mais comme il veut un [Int] il va falloir caster quand même.




     


     


    OK, tous en Swift, sans cast, mais ce n'est plus trié...



    let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

    let uniqueVals = Array(Set(vals))

    Mais, on a déjà  rédigé un OrderedSet en Swift https://github.com/Weebly/OrderedSet/blob/master/Sources/OrderedSet.swift

Connectez-vous ou Inscrivez-vous pour répondre.