Retourner deux valeurs

TUPLE

a marqué ce sujet comme résolu.

Bonjour :) ,

J’ai mon algorithme qui marche, mais j’aimerai apporté une modification. Ma fonction recherche dans un texte dans le message des client tout nombre de 5 à 4 chiffre de entre 60000 - 1000 (ex: 1001) si le client demande la commande 1005 comme exemple et me le retourne.

Mais je voudrai que si après avoir analyser le texte et trouve deux nombre de 5 à 4 chiffre de entre 60000 - 1000 (ex: 1001 et 3005) que cela me retourne tout les deux.

Au lieu de me récupérer normalement toutes les valeurs, elle me récupère qu’une seule même s’il y en a plusieurs alors que je retourne bien "order_name"


def detect_order_name(message):
    for text in [message["subject"],message["data"]]:
        order_name = "not found"
        match = re.search(r"\D(\d{4,5})\D","{}{}{}".format("a",text,"a"))
        if match:
            num = int(match.group(1))
            if num < 60000 and num > 1000:
                order_name = str(num)
                break
    return order_name


Il y a deux problèmes ici.

  • Tu as un break dans ta boucle ce qui veut dire que tu sors dès que tu trouves un nombre entre 1000 et 60000
  • Lorsque tu trouves un nombre entre 1000 et 60000, tu l’assignes à order_name. Ce que tu veux, c’est plutôt que order_name soit une liste par exemple et faire order_name.append(str(num))
+3 -0

Je dois faire un return de order_name.append(str(num)) ?

def detect_order_name(message):
    for text in [message["subject"],message["data"]]:
        order_name = "not found"
        match = re.search(r"\D(\d{4,5})\D","{}{}{}".format("a",text,"a"))
        if match:
            num = int(match.group(1))
            if num < 60000 and num > 1000:
                order_name = str(num)
                break
    return order_name.append(str(num))
+0 -0

Je dois faire un return de order_name.append(str(num)) ?

mikesbita

Non, déjà parce que order_name.append renvoie None si order_name est une liste. Ensuite parce que tu n’as rien modifié du code précédent, donc order_name est toujours une chaîne de caractères (qui n’a pas de méthode append), et tu sors toujours de la boucle à la première valeur correspondante.

C’est à la place du break qu’il te faudrait conserver la valeur dans une liste.

Mais étant donné que tu itères juste sur une liste de deux éléments que tu viens de créer, la boucle est-elle vraiment nécessaire ? Ne pourrais-tu pas juste avoir une sous-fonction que tu appellerais sur tes deux valeurs ?

Après une étude approfondie, je pense que le problème vient de l’expression régulière dans ma re.search. J’ai essayé de remplacer re.search à re.findall.

def detect_order_name(message):
    for text in [message["subject"],message["data"]]:
        order_name = "not found"
        match = re.findall(r"\D(\d{4,5})\D","{}{}{}".format("a",text,"a"))
        if match:
            num = int(match.group(1))
            if num < 60000 and num > 1000:
                order_name = str(num)
                break
    return order_name.append(str(num))

J’ai revu l’algorithme pour virer la condition qui fait qu’elle s’arrête de remplir le tuple/liste.

Vous en dites quoi ?

def detect_order_name2(message):
    text = message["subject"] + message["data"]
    order_name = list()
    lstr_order_name = re.findall(r"\d+", text)
    lint_order_name = [int(x) for x in lstr_order_name]
    for num in lint_order_name :
        if num < 60000 and num > 1000:
            order_name.append(num)
    print(order_name)
    if order_name :
        return order_name
    else :
        return "not_found"

Salut,

Ton code est nettement plus propre qu’au début.

Quelques points.

  • Tu peux écrire 1000 < num < 60000 au lieu de num < 60000 and num > 1000.
  • Plutôt que renvoyer une valeur spéciale "not_found", tu peux simplement renvoyer la liste vide lorsqu’il n’y a pas de match. Ça t’évite une condition dans ta fonction, et à chaque fois que tu l’appelles. Si tu tiens absolument à renvoyer une valeur spéciale plutôt qu’une liste vide, l’objet idiomatique à renvoyer pour marquer une valeur manquante est None plutôt qu’une chaine arbitraire.
  • Tu n’as pas besoin de deux listes lstr_order_name et lint_order_name différentes.
  • Tu peux construire order_name avec une liste en compréhension : order_name = [n for n in lint_order_name if 1000 < n < 60000], et comme c’est la valeur que tu renvoies (voir le 2eme point) tu n’as pas besoin de la variable order_name et tu peux renvoyer la liste en compréhension directement.

Quelques commentaires seraient bienvenus.

Le seule commentaire utile ici serait plutôt une docstring. Le code est simple et sans magie bizarre, le commenter n’apporte rien à part le risque de ne pas mettre à jour les commentaires si la fonction change plus tard.

+1 -0

Quelques commentaires seraient bienvenus.

Le seule commentaire utile ici serait plutôt une docstring. Le code est simple et sans magie bizarre, le commenter n’apporte rien à part le risque de ne pas mettre à jour les commentaires si la fonction change plus tard.

adri1

J’ai mis cela parce que je ne comprenais pas les lignes 4 et 5.

+0 -0

Deux raisons principalement pour moi :

  • L’OP cherche à renvoyer au maximum deux valeurs. La boucle semble déjà peu pertinente, le générateur l’est encore moins.
  • De plus il semble débuter en Python, les générateurs sont plutôt d’un niveau moyen à avancé.

Deux raisons principalement pour moi :

  • L’OP cherche à renvoyer au maximum deux valeurs. La boucle semble déjà peu pertinente, le générateur l’est encore moins.
entwanne

Non, ou alors j’ai mal compris …

tout nombre de 5 à 4 chiffre de entre 60000 - 1000
if num < 60000 and num > 1000:

il peut donc y en avoir 59000

  • De plus il semble débuter en Python, les générateurs sont plutôt d’un niveau moyen à avancé.
entwanne

Cet argument est plus recevable mais si l’OP est curieux, il fait une recherche ou demande plus d’explications. Sinon il ne peut pas deviner que cela existe :)

  • L’OP cherche à renvoyer au maximum deux valeurs. La boucle semble déjà peu pertinente, le générateur l’est encore moins.
entwanne

Non, ou alors j’ai mal compris …

tout nombre de 5 à 4 chiffre de entre 60000 - 1000
if num < 60000 and num > 1000:

il peut donc y en avoir 59000

Angelo

Mais il explique ne vouloir renvoyer que deux nombres, l’un trouvé dans le sujet du message et l’autre dans les données. La recherche de la valeur se fait à l’aide d’une expression rationnelle, pas d’une boucle.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte