遍历列表

Iteration through a list

我对 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 returns 只是代表一天的数字,即 30

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

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

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

当 4 月开始时,列表将更新为 4 月的每个星期一到 5 月初的新日期

next takes an optional default 即当可迭代对象为空时 returned。如果 color_sack 始终将下个月的第一天放在最后一个位置,则 return 它作为默认值:

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

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

  1. 检查 color_sack 中是否有任何日期大于
    如果是今天的日期,那么我们就得出那个日期。在我们的例子中,列表中没有日期大于 30.
  2. 如果 1st 条件失败,我们现在在 color_sack 中找出最大日期的索引,在我们的例子中,最大日期是 30,它的索引是 4,现在我们发现是否有 idx 大于列表中最大日期的索引,如果是,那么我们 return 那个日期。

此算法将符合当月的任何日期,例如 March。新的一个月一开始,例如。 "April starts the list will be updated with the new dates for Mondays in April through to the beginning of May"。 所以这个算法会一直遵守。

试试这个:

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

感谢您的帮助,我已经使用了 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()

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