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

资讯详情

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

freeCodeCamp 每日编程挑战解析:用 Python 求段落中最频繁的三个单词(Challenge 35: Word Frequency)

freeCodeCamp 每日编程挑战解析:用 Python 求段落中最频繁的三个单词(Challenge 35: Word Frequency) freeCodeCamp 每日编程挑战解析用 Python 求段落中最频繁的三个单词Challenge 35: Word Frequency【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇以 freeCodeCamp 开源仓库中「Dev Playground」超级块内每日编程挑战Daily Coding Challenge第 35 题「Word Frequency」为对象完整拆解题目规格、官方测试用例与参考解法并溯源该练习题从 Markdown 课程文件、GraphQL 抓取、数据库种子脚本到线上 API 路由的完整工程链路。读完本文你既能独立写出通过全部测试的get_words实现也能理解这道题在 freeCodeCamp 实际产品中是如何被分发与验证的。挑战背景这道题在仓库中的位置「Word Frequency」是每日编程挑战系列的第 35 题其唯一来源是课程 Markdown 文件 curriculum/challenges/english/blocks/daily-coding-challenges-python/68b06e589bf227324381476f.md文件头部的 YAML 元数据定义了它的身份id: 68b06e589bf227324381476f全局唯一挑战 ID同时也是种子脚本写入 MongoDB 时使用的_idtitle: Challenge 35: Word FrequencychallengeType: 29题目类型标记用于客户端渲染与提交流程dashedName: challenge-35。在块定义文件 curriculum/structure/blocks/daily-coding-challenges-python.json 中它排在daily-coding-challenges-python块的第 35 位helpCategory为PythonblockLayout为legacy-challenge-list并启用了usesMultifileEditor。该块隶属「Dev Playground」超级块是每日挑战的内容源头种子脚本 tools/daily-challenges/seed-daily-challenges.ts 中硬编码了EXPECTED_CHALLENGE_COUNT 365即这套每日挑战共 365 道覆盖一整年。值得一提的工程细节是同一个挑战 ID 也存在于 JavaScript 块中即 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/68b06e589bf227324381476f.md。这意味着 Word Frequency 是一道双语言题目——JavaScript 与 Python 各有一份描述、测试与起始代码种子脚本会按标题一一配对详见后文「从练习题到线上功能」。题目规格输入与输出的精确约定原文档的--description--部分给出了如下完整需求给定一段话paragraph返回一个由出现次数最多的三个单词组成的数组。段落中的单词以空格分隔忽略大小写例如Hello与hello视为同一个单词忽略标点标点仅包括逗号,、句点.和感叹号!返回数组中的所有单词必须是小写返回数组按出现次数降序排列出现次数最多的单词排在最前。约定函数签名为get_words(paragraph)参数为字符串返回值为字符串数组。这组规则界定了三个核心加工步骤清洗去标点、统一小写→ 分词按空格拆分→ 计数并排序取前三。官方测试用例如何验证你的实现原文档--hints--提供了三个测试用例每个测试都嵌在 JavaScript 的runPython调用中借助 Python 标准库unittest.TestCase在浏览器端执行断言用例一句子中出现多次编码主题词验证计数与降序。({test: () { runPython( from unittest import TestCase TestCase().assertEqual(get_words(Coding in Python is fun because coding Python allows for coding in Python easily while coding), [coding, python, in])) }})用例二句子含句点与感叹号验证标点剥离与大小写归一。({test: () { runPython( from unittest import TestCase TestCase().assertEqual(get_words(I like coding. I like testing. I love debugging!), [i, like, coding])) }})用例三标点密集、单词重复的句子验证频率统计的稳定性。({test: () { runPython( from unittest import TestCase TestCase().assertEqual(get_words(Debug, test, deploy. Debug, debug, test, deploy. Debug, test, test, deploy!), [debug, test, deploy])) }})三个用例覆盖了本题的核心边界大小写混合、句点/逗号/感叹号同时出现、以及多个单词出现次数相同用例二中coding、testing、love、debugging均只出现一次时取最靠前的词。这种「测试字符串内嵌断言」的写法是 freeCodeCamp 挑战的标准形态——hints中的text与testString会被解析为课程测试节点最终通过runPython在沙箱中执行 Python 代码。起始代码你需要补全的骨架原文档--seed-contents--给出的起始代码如下函数当前仅把参数原样返回def get_words(paragraph): return paragraph你的任务是把这段骨架补全为满足上述五条规则、能通过全部三个测试的完整实现。参考解法逐行拆解官方答案原文档--solutions--提供了官方参考实现import re def get_words(paragraph): cleaned re.sub(r[.,?], , paragraph.lower()) words cleaned.split() freq {} for word in words: freq[word] freq.get(word, 0) 1 sorted_words sorted(freq.keys(), keylambda w: freq[w], reverseTrue) return sorted_words[:3]逐行解析其设计第一步清洗paragraph.lower()先统一小写满足规则 2、4随后re.sub(r[.,?], , ...)用正则替换的方式把,.?全部删掉规则 3。使用re模块而非str.replace链式调用是因为一次正则替换即可覆盖多个字符类代码更简洁。第二步分词cleaned.split()以空白为分隔符切分单词规则 1。Python 的str.split()在不传参时会按任意连续空白切分并自动丢弃空串因此即使出现多个连续空格也不会产生空词。第三步计数遍历词表用freq.get(word, 0) 1完成「读旧值、加一、写回」的计数惯用法等价于collections.Counter的手写版。这里体现了字典get方法带默认值参数的典型应用。第四步排序sorted(freq.keys(), keylambda w: freq[w], reverseTrue)按键单词在字典中查频次作为排序键降序排列。注意它排序的是去重后的键集合而非原始词表因此不会因为某词出现多次而重复计算。第五步截取切片[:3]取前三个最高频单词对应「最频繁的三个单词」的题目要求。复杂度上该实现为O(n m log m)其中n为段落单词总数清洗与计数均为线性扫描m为去重后的单词种类数排序开销。一个值得留意的源码细节标点集合与描述略有出入对照题目描述规则 3 声明标点仅为,.!与官方解法中的正则[.,?]可以发现一个有趣的出入正则实际剥离的是逗号、句点和问号并不包含感叹号!。但第三个测试用例结尾为deploy!依然能够通过——因为剥离后词表为[debug,test,deploy,debug,debug,test,deploy,debug,test,test,deploy!]其中deploy出现 2 次deploy!仅 1 次debug与test各 4 次取前三时deploy2 次恰好压过deploy!1 次入围。也就是说测试数据的设计让该差异没有暴露。编写自己的解法时若严格按照描述剥离!例如正则改为r[.,!]同样能通过全部测试这恰好说明以官方测试用例为准绳、同时遵循题目描述是最稳妥的策略。并列情形的顺序保证当多个单词频次相同如用例二中的coding、testing、love、debugging都只出现 1 次时Python 的sorted是稳定排序且本题的键源freq是普通字典Python 3.7 保持插入顺序因此并列单词按首次出现顺序保留coding得以进入结果数组。这一点对理解预期输出至关重要。进阶思考解法的可替换实现官方解法用字典 sorted思路直白、足够应付本题规模。若题目规模扩大或要求更严格的复杂度可考虑以下变体属扩展思考非仓库内容用collections.Counter(cleaned.split())一行完成计数语义更清晰用heapq.nlargest(3, freq, keyfreq.get)在词表很大时把排序降到O(n log 3)级别只需维护大小为 3 的堆将清洗正则收紧为re.sub(r[^\w\s], , paragraph.lower())可剥离所有非单词、非空白字符泛化标点集合。从练习题到线上功能这道题在 freeCodeCamp 中的完整链路Word Frequency 不只是静态练习题它经由dev-playground超级块进入每日挑战产品线形成了一条可完整追溯的工程链路内容源挑战 Markdown 文件即本题目所在文件被tools/daily-challenges的种子脚本消费。脚本 tools/daily-challenges/seed-daily-challenges.ts 通过 tools/daily-challenges/helpers.ts 中queryGraphQL向本地 Gatsby 客户端的 GraphQL 端点http://localhost:8000/___graphql发起查询按superBlock: dev-playground、block: daily-coding-challenges-python或-javascript过滤并标注「客户端需在运行中才能抓取到挑战数据」。双语言配对combineChallenges函数见 tools/daily-challenges/helpers.ts将同一挑战号的 JavaScript 与 Python 版本配对逐一校验标题、描述是否一致、测试数量是否相同任一不匹配即抛错随后以ObjectId(jsId)作为新文档_id写入 MongoDB 的DailyCodingChallenges集合。日期编排脚本从2025-08-11T00:00:00.000Z起逐日递增START_DATE在脚本中有硬编码校验防止意外修改并为每条记录生成challengeNumber、date、title、description、javascript/python两组tests与challengeFiles数据结构见 tools/daily-challenges/types.ts。写入采用replaceOne upsert的 bulkWrite 幂等策略重复运行不会产生重复文档运行前还会核对总数是否为 365。具体执行步骤见 tools/daily-challenges/README.md复制sample.env为.env、安装依赖、启动开启即将上线功能的主客户端然后在tools/daily-challenges下运行pnpm seed-daily-challenges。线上分发挑战数据由 API 服务对外提供。路由文件 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 定义了GET /daily-coding-challenge/date/:date、/daily-coding-challenge/day/:day、/daily-coding-challenge/today、/daily-coding-challenge/month/:month、/daily-coding-challenge/all、/daily-coding-challenge/newest共六个公开接口统一限制「不返回晚于美国中部时间当天」的题目并对非法日期格式返回 400、未找到返回 404同时埋点 Sentry 指标如dcc.challenge_viewed、dcc.challenge_not_found。值得注意该插件注释明确说明这些接口只负责获取挑战信息挑战提交仍走主挑战完成路由。客户端展示前端组件目录 client/src/components/daily-coding-challenge 下的widget.tsx当日挑战挂件与calendar.tsx日历视图负责把按日期分发的挑战渲染给学习者完成作答后进入课程进度体系。相关文件速查题目本体Pythoncurriculum/challenges/english/blocks/daily-coding-challenges-python/68b06e589bf227324381476f.md题目本体JavaScript 同 ID 配对版curriculum/challenges/english/blocks/daily-coding-challenges-javascript/68b06e589bf227324381476f.md块定义 curriculum/structure/blocks/daily-coding-challenges-python.json种子脚本与配对逻辑tools/daily-challenges/seed-daily-challenges.ts、tools/daily-challenges/helpers.ts、tools/daily-challenges/types.ts分发 APIapi/src/daily-coding-challenge/routes/daily-coding-challenge.ts前端组件client/src/components/daily-coding-challenge/widget.tsx、client/src/components/daily-coding-challenge/calendar.tsx【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表