
freeCodeCamp 每日编程挑战解析用 Python 切片与 f-string 实现 Phone Number Formatter【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp导读本文以 freeCodeCamp 开源仓库中 Challenge 51: Phone Number Formatter 为切入点完整讲解这道 Python 字符串格式化题目的需求、官方测试用例、解题思路与参考实现并延伸剖析该挑战在 freeCodeCamp 每日编程挑战Daily Coding Challenge体系中的位置以及它从课程文件到 API 路由、前端组件、数据库种子脚本的完整运行链路。读完本文你既能独立通过这道题目也能理解 freeCodeCamp 中challengeType: 29挑战从仓库源码到在线平台的运作方式。一、挑战概览一道经典的电话号码格式化题目该挑战位于daily-coding-challenges-python超级块中是该系列的第 51 道题。从 curriculum/structure/blocks/daily-coding-challenges-python.json 中的challengeOrder可以看到整个超级块按顺序收录了超过 350 道 Python 每日挑战从 Challenge 1: Vowel Balance 到 Challenge 200而本题目对应条目为{ id: 68b7cadffed0e75a517da671, title: Challenge 51: Phone Number Formatter }该文件的 frontmatter 还标明challengeType: 29即每日编程挑战专用类型。作为系列中的编号挑战它的难度设置偏基础重点考察**字符串切片slicing与格式化输出f-string**两个 Python 核心知识点。二、题目需求拆解题目的--description--部分非常简短只有一句话Given a string of eleven digits, return the string as a phone number in this format:D (DDD) DDD-DDDD.将其拆解为三个可执行约束约束说明输入一个由11 位数字组成的字符串例如05552340182输出格式D (DDD) DDD-DDDD其中D为单个数字格式含义后跟 1 位国家码country code括号内 3 位区号area code随后 3 位前缀prefix、短横线、4 位号码line number也就是说函数要做的工作本质上是把扁平的 11 位数字串按固定位置切分成四个语义段再按模板拼接全程不涉及任何算术运算或条件判断。三、官方测试用例分析hints文件中的--hints--部分给出了两组测试断言用于校验实现是否符合预期。它们被包裹在 JS 的runPython调用中实际执行的是 Python 标准库unittest({test: () { runPython( from unittest import TestCase TestCase().assertEqual(format_number(05552340182), 0 (555) 234-0182)) }})({test: () { runPython( from unittest import TestCase TestCase().assertEqual(format_number(15554354792), 1 (555) 435-4792)) }})逐位对照第一个用例可以直观看到切分位置输入: 0 5 5 5 2 3 4 0 1 8 2 索引: 0 1 2 3 4 5 6 7 8 9 10 |-----| |--------| |--------| 国家码 区号(1:4) 前缀(4:7) 后四位(7:) 输出: 0 (555) 234-0182两个用例分别覆盖了国家码为0和1的情形验证算法对首位的处理与其余 10 位按3-3-4分组的方式。注意区号555是北美虚构号码惯用的保留区段测试数据本身也沿用了这一惯例。四、从零解题官方参考实现逐行解读题目的--seed--部分给出了函数骨架def format_number(number): return number而--solutions--中的官方参考实现如下def format_number(number): country number[0] area number[1:4] prefix number[4:7] line number[7:] return f{country} ({area}) {prefix}-{line}4.1 四步切分参考实现用 4 次索引/切片操作把 11 位字符串切成 4 段变量切片表达式位置含义以05552340182为例countrynumber[0]首位国家码0areanumber[1:4]第 2~4 位区号555prefixnumber[4:7]第 5~7 位前缀234linenumber[7:]第 8 位到末尾号码0182Python 切片遵循左闭右开[start:stop]含start不含stop规则因此number[1:4]恰好取到索引 1、2、3 三个字符number[7:]省略终止位置表示取到字符串末尾天然适配后四位的语义也无需关心输入长度是否严格为 11——这既是简洁之处也是后续边界讨论的焦点。4.2 f-string 模板拼接最后一步使用 Python 3.6 的 f-string 字面量插值完成拼接return f{country} ({area}) {prefix}-{line}f...前缀允许在字符串内用{}直接嵌入变量格式化结果与需求中的模板D (DDD) DDD-DDDD一一对应与(、)、-为字面字符四个{}依次替换为国家码、区号、前缀、号码。4.3 在本地快速验证将官方实现保存为format_number.py用一段小脚本即可验证两个用例from unittest import TestCase def format_number(number): country number[0] area number[1:4] prefix number[4:7] line number[7:] return f{country} ({area}) {prefix}-{line} TestCase().assertEqual(format_number(05552340182), 0 (555) 234-0182) TestCase().assertEqual(format_number(15554354792), 1 (555) 435-4792) print(All tests passed.)五、边界情况与进阶实现讨论题目未明确要求处理非法输入但作为技术文章值得补充讨论几种常见的健壮性考量注意这些属于扩展思考通过题目官方测试并不需要5.1 输入长度校验若输入不是恰好 11 位切片方案不会报错但结果会出现偏差。可在函数入口增加长度守卫def format_number(number): if len(number) ! 11 or not number.isdigit(): raise ValueError(Number must be an 11-digit string) country number[0] area number[1:4] prefix number[4:7] line number[7:] return f{country} ({area}) {prefix}-{line}str.isdigit()同时排除了包含非数字字符的输入。5.2 正则表达式方案使用re模块做位置分组也是一种可读性较高的写法import re def format_number(number): match re.fullmatch(r(\d)(\d{3})(\d{3})(\d{4}), number) if not match: raise ValueError(Number must be an 11-digit string) country, area, prefix, line match.groups() return f{country} ({area}) {prefix}-{line}5.3 通用格式化思路的延伸这种按固定位宽重组字符串的思路在真实项目中非常常见例如把 10 位手机号格式化为XXX-XXX-XXXX、把日期字符串YYYYMMDD重组为YYYY-MM-DD等。同系列题目中Challenge 64: 24 to 12、Challenge 118: Date Formatter 等也都在训练同一类解析-重组-格式化的能力可以作为延伸练习。六、源码视角这道挑战如何跑在 freeCodeCamp 平台上该挑战不只是孤立的 Markdown 文件它是一整条每日编程挑战产品链路中的一环。理解这条链路有助于把握题目的实际运行形态。6.1 挑战文件的双语言配对结构在 tools/daily-challenges/seed-daily-challenges.ts 中可以看到每日挑战在入库时按日期一一配对 JavaScript 与 Python 两个版本fetchChallenges(javascript)与fetchChallenges(python)数量必须一致否则直接抛错并生成从2025-08-11起每天一道、共 365 道的序列。也就是说Challenge 51 的 Python 版本文题目与同名 JavaScript 版共享同一条数据库记录只是语言字段不同。6.2 客户端对挑战数据的结构校验前端在拿到每日挑战数据后会通过 client/src/utils/daily-coding-challenge-validator.ts 中的 Joi schema 做结构校验。该 schema 对每个语言版本要求tests由text与testString组成的数组对应本文--hints--中被runPython包裹的断言脚本challengeFiles包含fileKey与contents的文件数组对应本文--seed--中的format_number函数骨架。这解释了为什么题目描述、hints 与 seed 三者的结构缺一不可——它们最终会被序列化进数据库记录并被前端严格校验。6.3 每日挑战的 API 与前端组件API 侧每日挑战的读取接口实现在 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts提供GET /daily-coding-challenge/date/:date、/day/:day、/today、/month/:month、/all、/newest等公开路由并通过fastify.prisma.dailyCodingChallenges查询数据库。前端侧client/src/components/daily-coding-challenge/widget.tsx 提供了学习地图页与首页上的今日每日挑战入口点击后跳转到/learn/daily-coding-challenge/{MM-DD}对应的挑战页面client/src/components/daily-coding-challenge/calendar.tsx 则用于按日期浏览历史挑战。七、结语Challenge 51: Phone Number Formatter 是一道小题目、大背景的 Python 练习表面上只考察 11 位数字串按3-3-4分组并用 f-string 拼装背后却串联起 freeCodeCamp 每日编程挑战从 课程 Markdown 源文件、超级块结构配置、种子脚本、API 路由 到 前端组件 的完整闭环。掌握了切片与格式化这两个知识点并顺着源码链路理解挑战的运行机制你便具备了攻克同系列后续字符串处理题目的完整方法论。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考