[RESOLU] [SWIFT] Problème avec une regex

InsouInsou Membre
juillet 2016 modifié dans API UIKit #1

Bonjour tout le monde,


 


J'ai un léger soucis avec une regex, j'ai l'impression qu'elle est bonne mais j'ai aussi l'impression qu'il me manque une subtilité avec le language swift et du coup, elle ne valide pas ma chaine de caractères..


 


En gros, voici mon code :



let myString = "GMT+2" // ou UTC-3 etc etc
print(myString)
let matches = matchesForRegexInText("[a-zA-Z0-9_]+([+-][0-9]+)", text: myString)


print(matches)
print(matches.count)


func matchesForRegexInText(regex: String!, text: String!) -> [String] {
do {
print(regex)
let regex = try NSRegularExpression(pattern: regex, options: [])
let nsString = text as NSString
let results = regex.matchesInString(text,options: [], range: NSMakeRange(0, nsString.length))
return results.map { nsString.substringWithRange($0.range) }
} catch let error as NSError {
print("invalid regex: \(error.localizedDescription)")
return []
}
}

J'ai essayé plusieurs formes pour ma regex :



([a-zA-Z0-9_]+)+([+-][0-9]+)


[a-zA-Z0-9_]+([+-][0-9]+)


^\\w+([\\+-][0-9]+)$


\\w+([\\+-][0-9]+)

Mais aucune ne fonctionne..


Au mieux, elle me ressort ma chaine de caractère (GMT+2) alors que je devrais recevoir que la partie qui m'intéresse (en gros, j'ai besoin du nombre avec son opérateur (+ ou -)).


 


Du coup, où est-ce-que je me plante ?


 


Merci de votre aide :)


Mots clés:

Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    Pourquoi tu continues à  bricoler avec les dates ? C'est vraiment inutile. Il existe déjà  les bonnes solutions, profites-en !
  • Insou, si tu ne l'as pas encore fait, je te conseil d'explorer la question d'abord avec des regexp "triviales" et de plus en plus compliqués... Le tout dans un playground évidemment !


  • Pourquoi tu continues à  bricoler avec les dates ? C'est vraiment inutile. Il existe déjà  les bonnes solutions, profites-en !




     


    Comme je disais dans mon autre post, c'est parce que le composant qui me récupère la date me renvoi quelque chose de trop complexe pour ce dont j'ai besoin.. j'ai juste besoin de l'heure affiché et pas d'une date UTC, etc etc..


    C'est pas de ma faute si la base de donnée derrière a été mal conçue, j'y suis pour rien ^^


    Du coup, je me suis fait ma fonction pour récupérer l'heure qu'on voit quand on la sélectionne.. c'est tout !


    J'suis bien conscient qu'il y a d'autres solutions qui existe pour ça mais ça correspond pas à  mes besoins.


     




    Insou, si tu ne l'as pas encore fait, je te conseil d'explorer la question d'abord avec des regexp "triviales" et de plus en plus compliqués... Le tout dans un playground évidemment !




     


    Bah c'est exactement ce que j'ai fait.


    Quand je test des regex plus simple en swift, ça fonctionne.


    Quand je test celle-la en php, elle fonctionne aussi.


    C'est pour ça que je post ici, je me dis qu'il y a une subtilité du language avec les regex que j'ai dû manquer..


     


    Pour moi, si je décrypte celle-ci : 



    [a-zA-Z0-9_]+([+-][0-9]+)

    ça veut dire : 


    - j'ai une partie avec des lettres et des nombres (bon là  les nombres ne sont pas obligatoire) + une partie avec un "+" ou un "-" suivi d'un nombre


    Ce qui est le cas de mon string "GMT+2" ou "UTC-8" .. nan ?


    Je me plante quelque part ?

  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #5

    C'est quoi exactement que tu reçoives de ton composant ?


  • InsouInsou Membre
    juillet 2016 modifié #6

    En gros, je reçois une date complète alors que je voulais que l'heure sélectionnée (ex : 2016-06-28 11:30:00 +0000)


    Mais au final, ce soucis est résolu, je récupère ce que je veux via ma fonction (cf : http://forum.cocoacafe.fr/topic/14700-résolu-swift-problème-format-dateheure/?p=141689#11 )


     


    Le soucis est que je veux rendre ma fonction plus générique et du coup, je bloque juste sur la regex..


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #7

    Le regex n'est pas nécessaire pour le faire, tu pourrais utiliser NSDateFormatter et NSDateComponents pour extraire seulement l'heure et les minutes. Mais il faut, en plus, savoir le date afin que l'on puisse trouver ou calculer le décalage de l'heure qui s'applique pour le fuseau horaire de l'utilisateur.


     


    Tu peux nous donnez un exemple des vraies données d'entrée et de ce que tu veux trouver comme bilan ?


  • colas_colas_ Membre
    juillet 2016 modifié #8


    Le soucis est que je veux rendre ma fonction plus générique et du coup, je bloque juste sur la regex..

    Attention Insou, en voulant faire ça tu contreviens au principe YAGNI.

    Ce principe est vraiment important et il faut toujours en tenir compte, même si au final tu passes outre.


    (Je te laisse googleiser YAGNI)
  • LarmeLarme Membre
    juillet 2016 modifié #9

    http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns (obtenu via https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW13)

    Avec NSDateFormatter, apparemment, le truc serait "OOOO" ou "ZZZZ" à  la fin pour avoir un " The long localized GMT format. This is equivalent to the "OOOO" specifier. "



  • Le regex n'est pas nécessaire pour le faire, tu pourrais utiliser NSDateFormatter et NSDateComponents pour extraire seulement l'heure et les minutes. Mais il faut, en plus, savoir le date afin que l'on puisse trouver ou calculer le décalage de l'heure qui s'applique pour le fuseau horaire de l'utilisateur.


     


    Tu peux nous donnez un exemple des vraies données d'entrée et de ce que tu veux trouver comme bilan ?




     


    Regarde ma fonction, a la fin en commentaire, il y a les données de ce que je reçois..


    A chaque traitement que je fais, je met ce que ça me retourne en commentaire


    http://forum.cocoacafe.fr/topic/14700-résolu-swift-problème-format-dateheure/?p=141689#11


     


    Pour trouver le décalage horaire, j'utilise la fonction getTimeZone() (même lien, en début de code).


     




    Attention Insou, en voulant faire ça tu contreviens au principe YAGNI.

    Ce principe est vraiment important et il faut toujours en tenir compte, même si au final tu passes outre.


    (Je te laisse googleiser YAGNI)




     


    J'ai googlé et : " mettez toujours en oe“uvre les choses quand vous en avez effectivement besoin, pas lorsque vous prévoyez simplement que vous en aurez besoin "


    J'en ai effectivement besoin..


    ​En gros, là  ma fonction me renvoie un décalage horaire sous le format "UTC+2" (par exemple)


    ​En continuant mes tests, à  un moment je me retrouve avec un "GTM+2" (en changeant la langue du téléphone, la région, etc etc)


    Ma fonction est écrite de telle sorte qu'elle fonctionnera qu'avec les décalages horaires au format "UTC+x"


    à  cause de ma ligne : 



    let MyTimeZone = self.getTimeZone().stringByReplacingOccurrencesOfString("UTC", withString: "") // récupère le décalage UTC en supprimant UTC de la chaine // +2

    Ce qui est normal vu que je supprime le "UTC" d'un string.


    Pas de bol, ça ne fonctionnera pas avec un décalage en "GTM+x"


    Du coup, pour palier à  ça, je voulais juste faire une regex (que je pensais simple), pour garder que le décalage et supprimer tout ce qui se trouve avant..

  • Bon, j'ai trouvé comment corrigé ma regex !


     


    En fait, je ne sais pas pourquoi il ne fait pas 2 groupes quand je fais : 



    ([a-zA-Z0-9_]+)+([+-][0-9]+)

    Pour moi c'était censé me sortir un tableau du style : ["GTM","+2"] mais en fait, il me ressort l'ensemble qu'il trouve donc ["GTM+2"]


     


    Du coup, si je veux récupérer juste le (+/-)x sans le format devant, la bonne regex est : 



    [+-]([0-9]+)

    et là  j'ai bien mon ["+2"] (mon décalage horaire) 


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #12

    Je t'ai déjà  dit, tu n'as pas besoin des regexes. Essayes ce...



    {
    let initialString = "2016-06-28 09:45:13 +0000"

    let dateFormatter = NSDateFormatter()

    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZZZ"

    if let date = dateFormatter.dateFromString(initialString)
    {
    let calendar = NSCalendar.currentCalendar()

    let dateComponents = calendar.components([.Hour, .Minute], fromDate: date)

    print("\(dateComponents.hour):\(dateComponents.minute)") // 11:45

    }
    }

  • ah bah en effet, c'est carrément plus simple que c'que j'essaie de faire  :p


     


    J'ai remplacé hh par HH dans "yyyy-MM-dd hh:mm:ss ZZZZZ"


    Du coup, ça simplifie grandement ma rustine sur l'autre post..


    J'comprenais pas comment m'en sortir avec les dates et les décalages mais là  ton exemple est super clair, j'vais donc allé simplifier mon code de ce pas ^^


     


    Encore merci :)


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #14


    ah bah en effet, c'est carrément plus simple que c'que j'essaie de faire  :p




     


    Je t'ai dit  ::)


     




    J'ai remplacé hh par HH dans "yyyy-MM-dd hh:mm:ss ZZZZZ"




     


    Je m'excuse, tu as raison avec les heures de l'horloge 24h. Je l'ai remplacé


     




    Du coup, ça simplifie grandement ma rustine sur l'autre post..


    J'comprenais pas comment m'en sortir avec les dates et les décalages mais là  ton exemple est super clair, j'vais donc allé simplifier mon code de ce pas 




     


    De rien   8--)


  • Joanna CarterJoanna Carter Membre, Modérateur

    Petite question supplémentaire - qu'est-ce que tu aurais fait avec ton bidouillage pour les heures après 21h59 ?  :'(


  • Bah j'avais pas remarqué le soucis, j'm'en suis rendu compte 5 minutes avant que tu post.. du coup j'tentais de comprendre le pourquoi du comment et au final ta solution à  tout régler d'un coup.. pfiouf  o:)


  • Déjà , tu t'y prends mal pour faire ce que tu veux. Il y a tout un tas des classes Apple qui font ça pour toi. Il faut bien comprendre comment elles marchent.


    Ensuite, même si tu veux pas les utiliser, là  tu suis une méthode anti-YAGNI. Je comprends ton cheminement de pensée, j'aurais sûrement fait la même chose que toi à  ta place (regex et cie), mais là  en l'occurence, tu peux régler ce problème hyper facilement, en prenant les 4emes et 5emes caractères de ton String... À la limite, tu itères et quand tu tombes sur + ou - tu prends le chiffre qui suis.


    Tu as préféré faire une méthode hyper générale qui règle tous les cas imaginables. Encore une fois, je comprends ton positionnement. C'est vachement plus élégant de faire une regex que de prendre les 4emes et 5emes caractères. En plus, ça permet d'apprendre. Donc oui, je te plussoies.


    Mais ce n'est pas YAGNI.


    Comprends bien que je ne suis pas agressif et que je veux juste t'aider. YAGNI c'est hyper important, ce n'est pas un commandement impératif, mais il faut toujours écouter ce point de vue avant de se lancer dans un truc plus général que nécessaire. Perso, j'ai mis du temps à  l'apprendre et c'est pour ça que je te l'explique.
  • colas_colas_ Membre
    juillet 2016 modifié #18


    Bon, j'ai trouvé comment corrigé ma regex !


    En fait, je ne sais pas pourquoi il ne fait pas 2 groupes quand je fais :

    ([a-zA-Z0-9_]+)+([+-][0-9]+)
    Pour moi c'était censé me sortir un tableau du style : ["GTM","+2"] mais en fait, il me ressort l'ensemble qu'il trouve donc ["GTM+2"]


    Du coup, si je veux récupérer juste le (+/-)x sans le format devant, la bonne regex est :
    [+-]([0-9]+)
    et là  j'ai bien mon ["+2"] (mon décalage horaire)

    Sinon de mémoire, il faut que tu te penches plus sur les methodes regexp. La je pense qu'il te renvoie bien ce que tu veux : une sous-chaà®ne de ta String qui matche ta regexp. Ici: toute la String. Je suis sûr que si tu regardes les methodes tu trouveras comment ensuite accéder aux sous-groupes de ta regexp. Tiens-nous au courant ;-)
  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #19

    Pour les manipulations des dates, je te conseillerais fortement de regarder la vidéo 227 de WWDC 2013. Pareil pour tous qui lisent ce fil  B)


  • InsouInsou Membre
    juillet 2016 modifié #20

    Comprends bien que je ne suis pas agressif et que je veux juste t'aider. YAGNI c'est hyper important, ce n'est pas un commandement impératif, mais il faut toujours écouter ce point de vue avant de se lancer dans un truc plus général que nécessaire. Perso, j'ai mis du temps à  l'apprendre et c'est pour ça que je te l'explique.



     


    T'inquiète pas, je ne l'ai pas pris comme ça, je sais bien que c'est pour aider, on est là  pour ça ^^


     


    Pour le coup, j'ai abandonné l'histoire de la regex, même si elle corrige mon soucis, elle ne les résous pas tous..


    J'étais mal parti dès le départ avec cette histoire de date/heure, j'avais pas saisie le truc avec NSCalendar


    Du coup, j'étais parti pour me compliquer la vie alors que la solution de Joanna Carter est carrément plus simple/propre/logique ^^


  • colas_colas_ Membre
    juillet 2016 modifié #21
    Pour en revenir à  ces questions de regexp, est-ce que si je copie colle ce code (désolé du Objective C), tu t'exclames ah mais oui bien sûr, c'est comme ça qu'il fallait faire ?


    NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];


    if (match) {

    NSRange matchRange = [match range];

    NSRange firstHalfRange = [match rangeAtIndex:1];

    NSRange secondHalfRange = [match rangeAtIndex:2];

    }

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