十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

freeCodeCamp 每日编码挑战解析:Challenge 330「lowercase words」过滤全小写单词的实现与验证

freeCodeCamp 每日编码挑战解析:Challenge 330「lowercase words」过滤全小写单词的实现与验证 freeCodeCamp 每日编码挑战解析Challenge 330「lowercase words」过滤全小写单词的实现与验证【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇技术指南围绕 freeCodeCamp 开源课程仓库中的每日编码挑战Challenge 330: lowercase words挑战源文件展开完整解读题目要求、测试用例与官方参考解法并结合仓库中每日编码挑战的课程结构、前后端实现与数据灌入脚本说明这类挑战在 freeCodeCamp 中的实际运行链路。读完本文你将掌握基于split/filter/join流水线处理字符串过滤问题的方法并理解每日编码挑战从 Markdown 挑战文件到数据库、再到前端渲染与断言验证的完整机制。一、挑战背景什么是 freeCodeCamp 每日编码挑战在进入具体题目之前先交代它所在的环境。freeCodeCamp 仓库中维护着一个独立的课程块block名为daily-coding-challenges-javascript其元数据定义在 curriculum/structure/blocks/daily-coding-challenges-javascript.json。该块共包含365 道挑战Challenge 1 至 Challenge 365按天发布isUpcomingChange为true采用legacy-challenge-list布局并启用usesMultifileEditor多文件编辑器。Challenge 330 正是其中第 330 道紧邻 Challenge 329 Bucket Fill 与 Challenge 331 Nearest Multiple。从块结构可以推断每日编码挑战以一日一题的形式存在仓库根目录中的 tools/daily-challenges/seed-daily-challenges.ts 将挑战按每日递增的日期批量写入数据库第一条挑战对应2025-08-11UTC此后每条挑战日期顺延一天该脚本还以常量EXPECTED_CHALLENGE_COUNT 365校验挑战数量确保一年 365 天每天都有题可练。二、题目要求逐字解读Challenge 330 的英文原题如下位于挑战文件的# --description--部分Given a string, return only the words that are entirely lowercase, in their original order and with a space between each word.将其拆解为三条核心约束过滤条件只保留完全小写的单词entirely lowercase即单词中不允许出现任何大写字母顺序保持保留单词在原始字符串中的相对顺序original order输出格式每个保留的单词之间以一个空格分隔with a space between each word。题目没有要求修改单词本身、没有要求去重、也没有要求排序因此这是一个典型的筛选filter型字符串问题。值得注意的是toLowerCase()只作用于 ASCII 字母大小写转换因此像数字、标点这类没有大小写之分的字符不受影响——例如单词123与自身的小写形式相等会被视为全小写单词而保留这与参考解法中word word.toLowerCase()的判断逻辑一致。三、测试用例hints与断言行为分析挑战文件通过 5 组测试用例# --hints--部分定义了通过标准。freeCodeCamp 的挑战机制中每个 hint 都对应一条由assert构成的测试字符串只有全部通过才算挑战完成。下表完整列出这 5 组用例及其行为特征输入字符串期望输出覆盖的边界特征hello GOOD worldhello world过滤中间的全大写单词GOODthese are all lowercasethese are all lowercase全小写输入应原样返回不变式less is NoT moreless is more过滤混合大小写单词NoT首字母大写 全大写组合DonT eat pizza every OTHER dayeat pizza every day同时过滤DonT与OTHER保留单词间仍以单个空格连接the Super quick AND snEaky brown fox Leapt anD jumped over aNd AROUND the lazy SloW dogthe quick brown fox jumped over the lazy dog长句中过滤多种大写形态首字母大写、全大写、大小写混杂这些用例的assert.equal断言写法如下节选自 挑战源文件assert.equal(getLowercaseWords(hello GOOD world), hello world); assert.equal(getLowercaseWords(DonT eat pizza every OTHER day), eat pizza every day);从测试设计上可以归纳出判定全小写单词的标准只要单词中存在任何大写字母无论出现在首字母还是单词中部该单词就被排除。NoT、DonT、snEaky这类单词内含大写的用例专门用来防止解题者只按word[0]判断首字母大小写。四、种子代码seed与官方参考解法4.1 种子代码挑战文件# --seed--部分提供了函数骨架学习者需要在此完成实现function getLowercaseWords(str) { return str; }种子代码直接返回原字符串意味着不实现任何逻辑时全部测试都会失败。每日编码挑战在课程中被归类为challengeType: 28对应freecodecamp/shared中定义的 JavaScript 每日挑战类型在客户端渲染时通过多文件编辑器编辑函数在浏览器环境中运行并被测试断言验证。4.2 官方参考解法挑战文件# --solutions--部分给出的官方解法仅用一行完成全部需求function getLowercaseWords(str) { return str.split( ).filter(word word word.toLowerCase()).join( ); }其执行流程可以拆解为三个步骤str.split( )以单个空格为分隔符将字符串拆分为单词数组。注意这里使用的是普通空格 因此多个连续空格会产生空字符串元素空字符串 .toLowerCase()成立会被filter保留这是该解法对多余空格的一种隐性处理方式但从测试用例看题目输入均为单词间单个空格.filter(word word word.toLowerCase())保留与其全小写形式完全相等的单词。这是整个挑战的核心判定只要单词含有一个大写字母word.toLowerCase()就会改变其内容比较结果为false单词被过滤.join( )以单个空格连接过滤后的单词保证输出中单词间只有一个空格与题目with a space between each word的要求完全吻合。这一解法充分利用了 JavaScript 字符串与数组的链式 API是函数式风格map/filter/reduce 思维在字符串处理中的典型示范。五、深入学习路径可替换实现与易错点为了让解题者不只停留在背答案层面这里补充几种等价实现思路及其对应的易错点可用于自行验证或拓展练习正则表达式方案使用/\b[a-z]\b/之类的模式匹配全部由小写字母组成的词但需要注意\b词边界与标点、数字的交互且正则方案无法直接复用上面 5 组用例的语义例如单词含数字时行为会与参考解法不同因此以通过挑战测试为准推荐使用与官方解法语义完全一致的word word.toLowerCase()判定。显式循环方案function getLowercaseWords(str) { const words str.split( ); const result []; for (const word of words) { if (word word.toLowerCase()) { result.push(word); } } return result.join( ); }容易踩坑的点只判断首字母大小写如word[0] word[0].toLowerCase()会错误地保留NoT、DonT这类含内部大写字母的单词使用word word.toUpperCase()反推全大写再取反会误伤123、!!等不含字母的 token它们toUpperCase()后仍等于自身忘记join( )返回数组而不是字符串导致assert.equal全部失败使用replace或match时未考虑大小写混合单词被整体剔除的语义。六、从挑战文件到线上运行的完整链路Challenge 330 并非孤立的练习题文件它处于 freeCodeCamp 每日编码挑战的完整生产链路中。结合仓库源码这条链路可以分为四段6.1 课程侧挑战文件与结构定义挑战的原始内容题目描述、hints、seed、solution存放在 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/ 下每个挑战一个 Markdown 文件。其 frontmatter 中challengeType: 28是关键标记它让 curriculum/schema/challenge-schema.js 这类 Joi 校验challengeType: Joi.number().min(0).max(33).required()以及课程构建流程能识别出这是一道每日编码挑战并按对应模板渲染。6.2 数据侧GraphQL 抽取与数据库灌入tools/daily-challenges/seed-daily-challenges.ts 配合 tools/daily-challenges/helpers.ts 完成挑战数据入库脚本通过 GraphQL 查询端点http://localhost:8000/___graphql需要客户端以显示即将上线内容模式运行从dev-playground超级块中按challengeOrder升序拉取全部 JavaScript 与 Python 挑战combineChallenges将同一编号的 JS/Python 挑战合并为一条文档写入 MongoDB 的DailyCodingChallenges集合并使用挑战的id作为文档_id代码注释强调DO NOT CHANGE THE ID因为它同时被completedDailyCodingChallenges[]引用脚本内置多重一致性校验JS 与 Python 挑战数量必须相等、标题必须一致、描述必须一致、测试数量必须一致数量必须等于 365任何一项不满足都会抛出错误中断灌入每条挑战按START_DATE2025-08-11 UTC加上i * ONE_DAY_IN_MS生成日期脚本对开始日期做了硬编码保护防止发布后意外改动。灌入后的文档结构为_id、challengeNumber、title已去掉Challenge N:前缀、date、description已去除解析器添加的section iddescription包装见removeSection、javascript.tests/challengeFiles与python.tests/challengeFiles。6.3 API 侧按日期提供挑战内容api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 注册了 6 个公开的 GET 路由供客户端按日期或天数获取挑战GET /daily-coding-challenge/date/:date按YYYY-MM-DD精确日期查询日期晚于今天美国中部时间会返回 404GET /daily-coding-challenge/day/:day按MM-DD查询内部通过getSourceDate换算到源日期Challenge 330 对应的2026-06-19这类日期即由该逻辑得出GET /daily-coding-challenge/today返回今天的挑战GET /daily-coding-challenge/month/:month按YYYY-MM返回当月挑战列表只含id、challengeNumber、date、title且只返回不晚于今天的记录GET /daily-coding-challenge/all返回全部挑战的简要列表GET /daily-coding-challenge/newest返回最新一条挑战的日期。路由全部使用 Fastify TypeBox schema 做参数校验定义于 api/src/daily-coding-challenge/schemas/非法日期格式返回 400未找到返回 404并对各类结果打点 Sentry 指标如dcc.challenge_viewed、dcc.challenge_not_found。挑战的提交不经过这些路由而是走主挑战完成流程见 api/src/daily-coding-challenge/README.md。6.4 客户端侧拉取、校验与渲染client/src/client-only-routes/show-daily-coding-challenge.tsx 是前端渲染入口根据 URL 中的日期调用/daily-coding-challenge/day/{MM-DD}获取挑战数据使用 client/src/utils/daily-coding-challenge-validator.ts 对返回数据做 schema 校验校验失败则抛出错误并显示未找到页面formatChallengeData将数据库文档重新组装为ShowClassic组件所需的 props其中 JavaScript 侧challengeType: 28、helpCategory: JavaScript文件内容来自javascript.challengeFiles[0].contents测试来自javascript.tests——Challenge 330 的 5 组assert.equal正是以这种方式进入浏览器测试运行器的用户在编辑器内编辑getLowercaseWords点击运行后由测试断言逐条验证全部通过即完成挑战。此外client/src/components/daily-coding-challenge/widget.tsx 提供了首页/学习地图上的入口组件将用户引导至/learn/daily-coding-challenge/{MM-DD}当天的题目页面。七、在本地运行与调试 Challenge 330若要在本地环境亲手验证 Challenge 330 的解法可以按以下方式操作仓库为只读以下均只涉及查看与本地运行本地校验解法正确性在 Node.js 环境直接粘贴参考解法与 5 组断言即可快速验证function getLowercaseWords(str) { return str.split( ).filter(word word word.toLowerCase()).join( ); } console.log(getLowercaseWords(hello GOOD world)); // hello world console.log(getLowercaseWords(DonT eat pizza every OTHER day)); // eat pizza every day console.log(getLowercaseWords( the Super quick AND snEaky brown fox Leapt anD jumped over aNd AROUND the lazy SloW dog )); // the quick brown fox jumped over the lazy dog查看课程结构与相邻挑战块定义 curriculum/structure/blocks/daily-coding-challenges-javascript.json 中challengeOrder完整列出了 365 道挑战的 id 与标题Challenge 330 的 id 为6a1d9f98e819ed70a0e994dc可通过它定位同目录下的相邻挑战329、331作对比练习。本地完整链路运行可选按照 tools/daily-challenges/README.md 的指引将sample.env复制为.env、安装依赖、以显示即将上线内容模式运行客户端然后执行pnpm seed-daily-challenges将挑战灌入本地 MongoDB即可配合 API 与前端页面复现完整的每日挑战体验。注意该流程面向本地开发环境脚本本身也提醒生产库的开始日期不应改动。八、小结Challenge 330 lowercase words 是一道精炼的字符串过滤题其核心判定word word.toLowerCase()一行代码便概括了完全小写的定义配合split/filter/join组成标准的函数式字符串处理流水线。同时从这道题出发可以看到 freeCodeCamp 每日编码挑战的工程全貌——挑战以 Markdown 文件为唯一事实来源经 GraphQL 抽取、一致性校验与日期灌入写入数据库再通过 Fastify API 按日/月/全部等维度对外提供最终由客户端校验 schema、组装 props 并交给浏览器测试运行器逐条断言。理解这条链路既能帮助你快速通过本挑战也能为你参与 freeCodeCamp 课程生态的阅读与维护提供清晰的上下文。延伸阅读挑战相邻题目Challenge 329: Bucket Fill、Challenge 331: Nearest Multiple可作同类型字符串/数学练习每日挑战的 Python 版本位于同结构块的daily-coding-challenges-python中。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表