尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

freeCodeCamp Python 每日编程挑战第 37 题:Sentence Capitalizer 句子首字母大写实现详解

freeCodeCamp Python 每日编程挑战第 37 题:Sentence Capitalizer 句子首字母大写实现详解 freeCodeCamp Python 每日编程挑战第 37 题Sentence Capitalizer 句子首字母大写实现详解【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇技术指南以 freeCodeCamp 开源课程中「Daily Coding Challenges」Python 系列第 37 道挑战Challenge 37: Sentence Capitalizer为研究对象完整拆解其题目约束、5 组官方测试用例与基于re.sub回调函数 首字符兜底处理的官方参考解法并结合本仓库中的挑战块结构与 API 源码说明该挑战在 freeCodeCamp 课程与「每日编程挑战」产品模块中的实际应用场景。读完本文你将掌握用正则表达式精确实现「段落级句首大写」的完整思路并理解 freeCodeCamp 挑战题challengeType 29的 Markdown 文件格式、测试断言写法与解题模板。挑战题源文件与课程定位本挑战对应的源文件位于仓库的 curriculum/challenges/english/blocks/daily-coding-challenges-python/68b06e589bf2273243814773.md文件的 YAML front-matter 记录了它的元数据--- id: 68b06e589bf2273243814773 title: Challenge 37: Sentence Capitalizer challengeType: 29 dashedName: challenge-37 ---其中challengeType: 29标识它属于「每日编程挑战」Daily Coding Challenge类型。该挑战属于名为daily-coding-challenges-python的挑战块block该块的结构定义在 curriculum/structure/blocks/daily-coding-challenges-python.json目前块内共包含 200 道编号连续的 Python 挑战Challenge 1 到 200块配置中helpCategory: Python、usesMultifileEditor: true、blockLayout: legacy-challenge-list且标记为isUpcomingChange: true。本挑战在该块中位于第 37 位紧随「Challenge 36: Thermostat Adjuster」68b06e589bf2273243814771.md其后是「Challenge 38: Slug Generator」68b06e589bf2273243814775.md整体呈现「按编号递进、难度螺旋上升」的系列化训练曲线。在产品侧「每日编程挑战」由 API 服务提供数据支撑api/src/daily-coding-challenge/routes/daily-coding-challenge.ts中暴露了date/:date、day/:day、today、month/:month、all、newest等公开 GET 路由通过 Prisma 查询dailyCodingChallenges表配套的 TypeBox 请求/响应 Schema 定义在 api/src/daily-coding-challenge/schemas/daily-coding-challenge.ts其中响应体包含id、date、challengeNumber、title、description以及javascript与python两种语言的tests测试文本 testString与challengeFiles种子代码文件字段——这正是本挑战在题面中同时给出 Python 种子代码与基于runPython的 JS 断言外壳的原因测试代码以字符串形式下发到前端再通过runPython在浏览器端执行。题目描述把每个句子的首字母大写本挑战的核心需求非常聚焦给定一段文字paragraph返回一个新段落其中每个句子的首字母都被大写。同时题目给出两条必须严格遵守的约束其余所有字符必须原样保留不能改变大小写之外任何内容句子的结尾可以是一个句号.、一个或多个问号?、一个或多个感叹号!。也就是说句子分隔符是一个可重复的标点簇如...、!!、???、!!!、甚至!!!与???连写紧随其后出现的第一个小写字母需要被转为大写而分隔符本身与中间可能出现的空白包括空格都要保持不变。这一需求在真实文本处理场景中很常见例如用户生成的评论、聊天记录、邮件摘要等自由文本常常缺失句首大写做展示前需要「自动润色」。而它的难点恰恰在于「句子边界」的定义——不是简单按单个.切分而是要正确处理连续标点、标点后带空格、以及段首本就小写的情况。官方测试用例逐条拆解原题面通过 5 组测试用例--hints--节精确定义了「正确行为」的边界。每组用例都是一段内嵌 JS 断言({test: () { runPython(...) }})其中runPython内部使用 Python 标准库unittest的TestCase().assertEqual(...)进行相等断言。逐条如下输入期望输出覆盖的边界this is a simple sentence.This is a simple sentence.段首小写 → 首字母大写hello world. how are you?Hello world. How are you?句号分隔 问号结尾i did todays coding challenge... it was fun!!I did todays coding challenge... It was fun!!连续...与连续!!作为分隔簇且保留原样crazy!!!strange???unconventional...sentences.Crazy!!!Strange???Unconventional...Sentences.连续标点簇之间无空格也要切分theres a space before this period . why is there a space before that period ?Theres a space before this period . Why is there a space before that period ?标点与下一个句子首字母之间带空格也要切分且空格保留从这些用例可以归纳出 3 个必须满足的行为契约段首兜底整段文字的第一个字符如果是小写字母也要大写用例 1/2/3/5 都涉及标点簇整体作为分隔符...、!!、???等连续标点不会被拆散下一个句子从标点簇之后的第一个字符开始允许「无空格」与「带空格」两种衔接方式crazy!!!strange这种无空格的紧贴情况和period . why这种带空格的松散情况都必须正确处理且空格数量原样保留。官方参考解法基于 re.sub 回调的两步策略题面--solutions--节给出的官方解法如下其核心是「一次re.sub替换 一次首字符兜底」的两步策略import re def capitalize(paragraph): def repl(match): return match.group(1) match.group(2) match.group(3).upper() result re.sub(r([.!?])(\s*)([a-z]), repl, paragraph) if result and result[0].islower(): result result[0].upper() result[1:] return result第一步用正则定位每个「句子起点」re.sub的正则模式([.!?])(\s*)([a-z])是本题的精华拆开看包含三个分组分组 1([.!?])—— 一个或多个句末标点.,!,?保证...、!!、???、!!!这类连续标点簇被当作一个整体匹配。注意它匹配的是「任意组合」的连续标点因此crazy!!!strange???中!!!与???会被分别识别为两个句子边界分组 2(\s*)—— 零个或多个空白字符空格、Tab、换行等。*允许「无空格紧贴」!!!strange与「带空格」period . why两种形态都命中且由于这一组被完整捕获并原样回填空白数量不会被改动分组 3([a-z])—— 紧接着的一个小写字母即「下一句的首字母」。三组匹配到后由回调函数repl完成拼接match.group(1) match.group(2) match.group(3).upper()也就是「原样保留标点簇 原样保留空白 将首字母转大写」其余所有字符天然不被触碰从而满足「所有其他字符原样保留」的约束。第二步处理段首小写的兜底re.sub只在「标点之后」的位置生效段落的第一个句子前面没有标点因此如果段落以一个小写字母开头例如this is a simple sentence.正则不会命中它。解法用if result and result[0].islower():做一次显式兜底仅当结果非空且首字符是小写字母时用result[0].upper() result[1:]替换首字符其余部分原样保留。这两个步骤叠加后官方解法对全部 5 组测试用例的输出已在本仓库环境中实测验证通过例如i did todays coding challenge... it was fun!! - I did todays coding challenge... It was fun!! crazy!!!strange???unconventional...sentences. - Crazy!!!Strange???Unconventional...Sentences. theres a space before this period . why is there a space before that period ? - Theres a space before this period . Why is there a space before that period ?学习者的解题入口种子代码题面--seed-contents--节给出了供学习者填充的种子代码即所有解法必须围绕的函数签名def capitalize(paragraph): return paragraph这实际上是 freeCodeCamp 挑战的标准「脚手架」模式函数名、参数、返回值结构已经定死学习者只需要补全中间逻辑。对本题而言函数接收一个字符串paragraph返回处理后的新字符串种子代码默认原样返回因此必须实现「句子边界检测」与「首字母大写」逻辑任何缺失边界处理例如只调用str.capitalize()/str.title()或只处理单个.的实现都会被上述 5 组用例拦截。值得注意的一个思路陷阱str.capitalize()只会把整段文字的第一个字母大写无法处理段内多句子str.title()会把每个单词都大写破坏「其余字符原样保留」的约束。因此本题的正确方向必须是基于正则的句子边界定位而非 Python 字符串内置的大小写转换方法。扩展思考正则模式的局限与改进方向官方解法已经足够通过全部用例但从工程视角仍可讨论其边界帮助读者建立更完整的认知对非小写字母开头的句子模式([.!?])(\s*)([a-z])只大写小写字母。若标点后紧跟大写字母、数字或其它字符则不会被改写——对本题而言这是刻意为之约束只要求首字母大写且其余字符保留符合「不越权改动」的设计段首空白若段落以空白开头再接小写字母第二步兜底只检查result[0]会漏掉该场景。可用re.sub(r^(\s*)([a-z]), lambda m: m.group(1) m.group(2).upper(), result)之类的模式扩展覆盖多语言文本[a-z]仅覆盖 ASCII 小写字母对含重音字符如 é、ü的文本不生效。生产环境中若需支持多语言应改用 Unicode 感知的大小写判定如str.islower()结合逐字符处理或re的 Unicode 标志。从源码结构看官方解法刻意保持了「约束优先、最小改动」的克制风格只处理题目明确要求的边界形态不引入对额外场景的过度处理这对学习者理解「以测试为契约」的解题方式很有参考价值。相关资源索引挑战题面、测试与官方解法curriculum/challenges/english/blocks/daily-coding-challenges-python/68b06e589bf2273243814773.md前一道挑战Thermostat Adjustercurriculum/challenges/english/blocks/daily-coding-challenges-python/68b06e589bf2273243814771.md挑战块结构与完整题目顺序curriculum/structure/blocks/daily-coding-challenges-python.json每日编程挑战 API 路由api/src/daily-coding-challenge/routes/daily-coding-challenge.ts每日编程挑战响应 Schemaapi/src/daily-coding-challenge/schemas/daily-coding-challenge.ts日期解析与循环映射工具函数api/src/daily-coding-challenge/utils/helpers.ts【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表