Python:将 ('Monday' 、 'Tuesday' 、 'Wednesday' ) 转换为 'Monday to Wednesday'

标签 python datetime date

我得到一个星期几的序列。我想做的 Python 代码:

def week_days_to_string(week_days):
    """
    >>> week_days_to_string(('Sunday', 'Monday', 'Tuesday'))
    'Sunday to Tuesday'
    >>> week_days_to_string(('Monday', 'Wednesday'))
    'Monday and Wednesday'
    >>> week_days_to_string(('Sunday', 'Wednesday', 'Thursday'))
    'Sunday, Wednesday, Thursday'
    """
    if len(week_days) == 2:
       return '%s and %s' % weekdays
    elif week_days_consecutive(week_days):
       return '%s to %s' % (week_days[0], week_days[-1])
    return ', '.join(week_days)

我只需要 week_days_consecutive 函数(最难的部分)。

我有什么想法可以实现这一目标吗?

澄清:

我的措辞和例子引起了一些困惑。我不仅想将此功能限制在工作周内。我想考虑一周中的所有日子(S、M、T、W、T、F)。很抱歉昨晚没说清楚。编辑了问题的正文以使其更清楚。

编辑:投入一些 Spanner

环绕序列:

>>> week_days_to_string(('Sunday', 'Monday', 'Tuesday', 'Saturday'))
'Saturday to Tuesday'

并且,根据@user470379 和可选:

>>> week_days_to_string(('Monday, 'Wednesday', 'Thursday', 'Friday'))
'Monday, Wednesday to Friday'

最佳答案

我会通过以下方式解决这个问题:

  • 创建一个将日期名称映射到它们的顺序索引的字典
  • 将我输入的日期名称转换为它们的顺序索引
  • 查看生成的输入索引并询问它们是否是连续的

使用 calendar.day_namerange 和一些用于理解的方法,您可以这样做:

day_indexes = {name:i for i, name in enumerate(calendar.day_name)}
def weekdays_consecutive(days):
    indexes = [day_indexes[d] for d in days]
    expected = range(indexes[0], indexes[-1] + 1)
    return indexes == expected

一些其他选项,具体取决于您的需要:

  • 如果您需要 Python < 2.7,您可以使用:

    day_indexes = dict((name, i) for i, name in enumerate(calendar.day_name))
    
  • 如果您不想允许星期六和星期日,只需剪掉最后两天:

    day_indexes = ... calendar.day_name[:-2] ...
    
  • 如果您需要在周日之后换行,可能最简单的方法是检查每一项是否比前一项多,但要以 7 为模:

    def weekdays_consecutive(days):
        indexes = [day_indexes[d] for d in days]
        return all(indexes[i + 1] % 7 == (indexes[i] + 1) % 7
                   for i in range(len(indexes) - 1))
    

更新:对于扩展问题,我仍然会坚持使用他们的 day-to-index dict,但我会:

  • 找到连续几天停止运行的所有索引
  • 如有必要,将日期换行以获得最长可能的天数
  • 将日子分组到他们的连续跨度中

这是执行此操作的代码:

def weekdays_to_string(days):
    # convert days to indexes
    day_indexes = {name:i for i, name in enumerate(calendar.day_name)}
    indexes = [day_indexes[d] for d in days]

    # find the places where sequential days end
    ends = [i + 1
            for i in range(len(indexes))
            if (indexes[(i + 1) % len(indexes)]) % 7 !=
               (indexes[(i) % len(indexes)] + 1) % 7]

    # wrap the days if necessary to get longest possible sequences
    split = ends[-1]
    if split != len(days):
        days = days[split:] + days[:split]
        ends = [len(days) - split + end for end in ends]

    # group the days in sequential spans
    spans = [days[begin:end] for begin, end in zip([0] + ends, ends)]

    # format as requested, with "to", "and", commas, etc.
    words = []
    for span in spans:
        if len(span) < 3:
            words.extend(span)
        else:
            words.append("%s to %s" % (span[0], span[-1]))
    if len(days) == 1:
        return words[0]
    elif len(days) == 2:
        return "%s and %s" % tuple(words)
    else:
        return ", ".join(words)

您也可以尝试以下而不是最后一个 if/elif/else block 来在最后两个项目之间获得一个“and”并在其他所有项目之间获得逗号:

    if len(words) == 1:
        return words[0]
    else:
        return "%s and %s" % (", ".join(words[:-1]), words[-1])

这与规范略有不同,但在我看来更漂亮。

关于Python:将 ('Monday' 、 'Tuesday' 、 'Wednesday' ) 转换为 'Monday to Wednesday',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4482050/

相关文章:

sql - ORA-01821 : date format not recognized error for ISO 8601 date with local time

python - 在 pandas 中查找组中的第一个非零元素

python - 如何用 True、False 和颜色编码 Python 绘图来标记 Y 轴?

javascript - 在 Javascript 中移动(而不是卡住)日期/时间

c# - 验证日期是否在 SqlDbType.DateTime 范围内

java - 为什么将 1582 年之前的 Java 日期转换为带有 Instant 的 LocalDate 会给出不同的日期?

sql-server - 如何在MsSQL中创建created_at和updated_at字段?

python - Pandas 数据帧 : Operation per batch of rows

python - 将 pandas df 列转换为配对列表

python - 循环遍历日期字符串列表 : strptime outputs "Datetime.date(2011-7-5)" instead of (2011-7-5)