Je suis très nouveau dans Python d'où cette question.
J'ai une liste qui représente les dates c'est-à-dire les lundis de mars et début avril
next_rubbish_day = next(x for x in color_sack if x > todays_date.day) StopIteration
La liste, 'color_sack' est créé à partir d'un extrait du site Web de notre conseil local.
J'utilise
next_rubbish_day = next(x for x in color_sack if x > todays_date.day)
todays_date.day renvoie uniquement le nombre représentant le jour, soit 30
Cela a bien fonctionné tout le mois jusqu'à aujourd'hui 30, quand il affiche maintenant une erreur
[2, 9, 16, 23, 30, 6]
Est-il possible de parcourir la liste d'une meilleure façon afin que next_rubbish_day remplirait le 6 après le 30 de la liste ci-dessus. Je peux voir pourquoi cela ne fonctionne pas, mais je ne peux pas trouver une meilleure solution.
Lorsque le mois d'avril commencera, la liste sera mise à jour avec les nouvelles dates pour les lundis d'avril à début mai
3 Réponses :
Je pense que supposer que le dernier indice est la valeur par défaut est naïf; peut-être que cela fonctionnera la plupart du temps, jusqu'à ce que ce ne soit pas le cas…
@deceze Le PO dit "J'ai une liste qui représente les dates, c'est-à-dire les lundis de mars et début avril " et "Lorsque le mois d'avril commencera, la liste sera mise à jour avec les nouvelles dates pour les lundis d'avril jusqu'à début mai ". Ainsi, le "jour de repli" sera toujours là et toujours après les jours du mois en cours. Même si nous considérons des données erronées telles que "contient un ou plusieurs jours du mois suivant", il est facile de les nettoyer pour obtenir les données requises.
Que fait le * au début de cette ligne: * this_month, fallback_day = color_sack. Pas vu ça avant.
Tenez compte du fait que si votre mois actuel est mars et que la liste des dates correspondante est [2, 9, 16, 23, 30, 6]
et que la date du jour est 30
, en gros, ce que nous faisons est:
color_sack
est supérieure à 30
. 1st
échoue, nous trouvons maintenant l'index de la date maximum dans le color_sack
, dans notre cas la date maximum est 30
et son index est 4
, maintenant nous avons découvert s'il y a un idx
plus grand que l'index de date maximum dans la liste, si c'est alors nous retournons cette date.
Cet algorithme sera conforme à toutes les dates du mois en cours, par exemple Mars
. Dès que le nouveau mois commence par exemple. "Début avril, la liste sera mise à jour avec les nouvelles dates pour les lundis d'avril à début mai".
Donc, cet algorithme sera toujours conforme.
Essayez ceci:
9 16 23 6 6
print(next(next_rubbish_day(color_sack, 6))) print(next(next_rubbish_day(color_sack, 10))) print(next(next_rubbish_day(color_sack, 21))) print(next(next_rubbish_day(color_sack, 30))) print(next(next_rubbish_day(color_sack, 31)))
def next_rubbish_day(color_sack, todays_date): for idx, day in enumerate(color_sack): if day > todays_date or idx > color_sack.index(max(color_sack)): yield day
Merci pour l'aide, j'ai utilisé l'extrait de MisterMiyagi car cela semble fonctionner pour le moment.
Voici le code complet:
import datetime import requests import calendar from bs4 import BeautifulSoup from datetime import date def ord(n): # returns st, nd, rd and th return str(n) + ( "th" if 4 <= n % 100 <= 20 else { 1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th") ) # Scrapes rubbish collection dates URL = "https://apps.castlepoint.gov.uk/cpapps/index.cfm?roadID=2767&fa=wastecalendar.displayDetails" raw_html = requests.get(URL) data = BeautifulSoup(raw_html.text, "html.parser") pink = data.find_all('td', class_='pink', limit=3) black = data.find_all('td', class_='normal', limit=3) month = data.find('div', class_='calMonthCurrent') # converts .text and strip [] to get month name month = str((month.text).strip('[]')) todays_date = datetime.date.today() print() # creats sack lists pink_sack = [] for div in pink: n = div.text pink_sack.append(n) pink_sack = list(map(int, pink_sack)) print(f"Pink list {pink_sack}") black_sack = [] for div in black: n = div.text black_sack.append(n) black_sack = list(map(int, black_sack)) print(f"Black list {black_sack}") # creats pink/black list color_sack = [] color_sack = [None]*(len(pink_sack)+len(black_sack)) color_sack[::2] = pink_sack color_sack[1::2] = black_sack print(f"Combined list {color_sack}") print() print() # checks today for rubbish if todays_date.day in color_sack: print(f"Today {(ord(todays_date.day))}", end=" ") if todays_date.day in pink_sack: print("is pink") elif todays_date.day in black_sack: print("is black") # Looks for the next rubbish day next_rubbish_day = next( (x for x in color_sack[:-1] if x > todays_date.day), color_sack[-1], ) # gets day number day = calendar.weekday( (todays_date.year), (todays_date.month), (next_rubbish_day)) # print(next_rubbish_day) print(f"Next rubbish day is {(calendar.day_name[day])} the {(ord(next_rubbish_day))}" + (" and is Pink" if next_rubbish_day in pink_sack else " and is Black")) print()
Il y en a probablement tellement des moyens plus efficaces de le faire, je suis donc ouvert aux suggestions et j'apprends toujours.
Je viens de me rendre compte que cela n'a pas fonctionné car le 6 arrive comme vendredi parce que le programme pense que c'est mars au lieu d'avril. Je vais jeter un oeil à d'autres options ici
Une approche serait
next (itertools.drop while (lambda x: x <= todays_date.day, color_sack))
, mais cela se déclenchera, disons, le 31 lorsque tout i > les dates suivantes sont inférieures au jour en cours. Vous devrez parcourir cette liste avec une connaissance réelle du moment où les jours se dérouleront dans le mois suivant.Utilisez
next ((x for x in color_sack if x> todays_date.day), color_sack [-1])
pour obtenir le 6 avril lorsque vous êtes à la fin du mois de mars. Notez que cela ne vous dira pas réellement que votre résultat est le mois prochain (il indique simplement 6, pas 6 avril ou 6 mars). Travailler avec des dates réelles au lieu d'un simple jour du mois serait plus robuste.