1

我对 Python 很陌生,因此这个问题。

我有一个代表日期的列表,即三月的星期一和四月初

[2, 9, 16, 23, 30, 6]

列表“color_sack”是从我们当地议会网站上创建的。

我在用着

next_rubbish_day = next(x for x in color_sack if x > todays_date.day)

todays_date.day 只返回代表这一天的数字,即 30

这整个月都运行良好,直到今天 30 日,它现在显示错误

next_rubbish_day = next(x for x in color_sack if x > todays_date.day)
StopIteration

是否有可能以更好的方式逐步遍历列表,以便 next_rubbish_day 会在上面列表中的 30 之后填充 6。我可以看到为什么它不起作用但无法找到更好的方法。

当四月开始时,列表将更新为四月星期一到五月初的新日期

4

3 回答 3

0

感谢您的帮助,我使用了 MisterMiyagi 片段,因为目前似乎可以使用。

这是完整的代码:

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()

可能有很多更有效的方法可以做到这一点,所以我愿意接受建议并一直在学习。

于 2020-03-30T17:57:18.980 回答
0

考虑一下,如果您当前的月份是 March 并且相应的日期列表是[2, 9, 16, 23, 30, 6]并且今天的日期是30,那么基本上我们正在做的是:

  1. 检查其中是否有任何日期color_sack大于
    今天的日期,如果是,则我们得出该日期。在我们的例子中,列表中没有日期大于30
  2. 如果1st条件不成立,我们现在找出 中最大日期的索引color_sack,在我们的例子中,最大日期是30,它的索引是4,现在我们找出是否有一个idx大于列表中最大日期的索引,如果是然后我们返回那个日期。

该算法将符合当月的任何日期,例如March。一旦新的月份开始,例如。“4 月开始,列表将更新为 4 月的星期一到 5 月初的新日期”。所以这个算法将永远遵守。

尝试这个:

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

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)))

输出:

9
16
23
6
6
于 2020-03-30T08:54:19.707 回答
0

next当可迭代对象为空时返回可选的默认值。如果color_sack始终在最后一个位置具有下个月的第一天,则将其作为默认值返回:

next_rubbish_day = next(
    (x for x in color_sack[:-1] if x > todays_date.day),
    color_sack[-1],
)

请注意,此方案不会告诉您是否已翻转。它只会告诉你下一个日期是 6 日,而不是 4 月 6 日和 3 月 6 日。

为避免魔法索引,请考虑明确拆分您的列表并为每个部分指定正确的名称。

*this_month, fallback_day = color_sack
next_rubbish_day = next(
    (day for day in this_month if day > todays_date.day),
    fallback_day,
)

如果您需要了解月份,请StopIteration明确处理:

try:
    day = next(x for x in color_sack[:-1] if x > todays_date.day)
except StopIteration:
    day = color_sack[-1]
    month = 'next'
else:
    month = 'this'
print(f'Next date is {day} of {month} month')
于 2020-03-30T08:34:56.367 回答