news 2026/9/8 20:02:08

freeCodeCamp 每日编程挑战 15:toCamelCase 驼峰转换的题目拆解与源码级解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
freeCodeCamp 每日编程挑战 15:toCamelCase 驼峰转换的题目拆解与源码级解析

freeCodeCamp 每日编程挑战 15:toCamelCase 驼峰转换的题目拆解与源码级解析

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

本文围绕 freeCodeCamp 课程库中 JavaScript 每日编程挑战(Daily Coding Challenges)的第 15 题——字符串驼峰命名转换(camelCase)展开:完整继承原题目的规格说明与全部官方测试用例,并基于课程块配置、挑战类型定义等仓库源码,讲解该题在平台中的组织方式、官方解法的每一步原理,以及实现时需要规避的典型陷阱。读完本文,你将能够独立实现一个能处理连续分隔符、大小写混杂输入的toCamelCase函数,并理解它在 freeCodeCamp 课程体系中的定位。

题目背景:这道题在课程体系中的位置

该题位于课程块daily-coding-challenges-javascript中,源文件为 Challenge 15: camelCase,其 Front Matter 中的关键元数据为:

id: 6821ebd4237de8297eaee791 title: "Challenge 15: camelCase" challengeType: 28 dashedName: challenge-15

challengeType: 28对应每日编程挑战中的 JavaScript 类型。这一点可以从共享包的挑战类型定义中得到印证:在 challenge-types.ts 中,dailyChallengeJs的编号正是 28(dailyChallengePy为 29),并由此派生了以下工具函数:

  • getIsDailyCodingChallenge(challengeType):判断某个挑战类型是否属于每日编程挑战(仅dailyChallengeJsdailyChallengePy两种);
  • getDailyCodingChallengeLanguage(challengeType):把挑战类型映射为语言标识,本题即映射为javascript
  • 在「测试代码存放位置」的映射表中,dailyChallengeJs指向tests,即题目内置的断言测试就是判分依据。

从课程块的结构文件 daily-coding-challenges-javascript.json 还可以看到该块的运行特征:

  • challengeOrder中 Challenge 15 恰好排在 "Challenge 14: Character Battle" 与 "Challenge 16: Reverse Parenthesis" 之间,整块包含 200 道以上的挑战;
  • usesMultifileEditor: true:编辑器支持多文件;
  • blockLayout: "legacy-challenge-list":以传统列表形式浏览题目;
  • helpCategory: "JavaScript":帮助分类归属 JavaScript。

在平台的运行链路上,这类题目由 tools/daily-challenges 提供的 seed 脚本从 "Dev Playground" 超块读取挑战并写入数据库的DailyCodingChallenges集合;前端展示侧由 api/src/daily-coding-challenge 下的路由提供每日挑战的查询接口,而挑战的提交判分仍走主 API。简言之,本文的这道题是一道典型的「断言驱动」编程题:通过仓库内嵌的assert测试即可完整验证你的实现。

题目规格:四条转换规则

原题给出的任务描述是:给定一个字符串,按以下规则返回它的驼峰命名(camel case)版本:

  1. 单词之间的分隔符是空格()、短横线(-)、下划线(_)三类字符,连续的任意多个分隔符都视为一个单词边界("Treat any sequence of these as a word break");
  2. 第一个单词整体转为小写;
  3. 其后每个单词首字母大写、其余字母小写;
  4. 所有空格和分隔符都要被移除。

这四条规则里最容易被忽略的是第 1 条:分隔符不是「单个字符」而是「一个序列」。比如输入peg__leg----and__----各自只算一个边界,不能把连续的-当作多个单词之间的额外空词处理——否则 join 之后会产生多余的字母或大小写异常。

官方测试用例:判分依据

原题目共给出 5 组断言用例,覆盖了从简单到复杂的典型输入,这也是本仓库对该题判分的完整依据(# --hints--段):

// 基础用例:单个空格分隔 assert.equal(toCamelCase("hello world"), "helloWorld"); // 大小写规整:全大写输入需先统一小写再按规则转换 assert.equal(toCamelCase("HELLO WORLD"), "helloWorld"); // 混合分隔符:空格与短横线并存 assert.equal(toCamelCase("secret agent-X"), "secretAgentX"); // 大小写混杂:中间词部分小写 assert.equal(toCamelCase("FREE cODE cAMP"), "freeCodeCamp"); // 压力用例:连续分隔符(__、-、----、_ _ 等)混合出现 assert.equal( toCamelCase( "ye old-_-sea faring_buccaneer_-_with a - peg__leg----and a_parrot_ _named- _squawk" ), "yeOldSeaFaringBuccaneerWithAPegLegAndAParrotNamedSquawk" );

最后一组是最关键的边界用例:_ _(下划线+空格+下划线)这种「跨类型连续分隔符」必须折叠为一个边界;a - peg__leg中间夹着空格的孤立-也要正确归位。若实现只对单一字符分隔(如直接split(' ')或逐字符判断),此用例必然失败。

题目的种子代码(# --seed--段)是一个待实现的空壳:

function toCamelCase(s) { return s; }

官方解法逐行解析

原题目附带的参考实现(# --solutions--段)如下:

function toCamelCase(s) { const words = s.replace(/[_\- ]+/g, ' ').split(' '); return words.map((word, i) => { if (i === 0) { return word.toLowerCase(); } else { const tempWord = word.split(''); return tempWord.shift().toUpperCase() + tempWord.join('').toLowerCase(); } }).join('') }

可以把它拆解为三个阶段:

阶段一:分隔符归一化。s.replace(/[_\- ]+/g, ' ')用一个正则把「一个或多个空格/短横线/下划线」统一替换为单个空格。正则[_\- ]+中:

  • 字符类[_\- ]同时收录空格、-(在字符类内\-\为防御性转义)、_
  • 量词+落实了题目第 1 条规则——任意长度的分隔符序列只算一个边界;
  • 全局标志g保证整串所有边界都被替换,而不是只处理第一个。

归一化之后字符串里只剩下「单词 + 单个空格」两种成分,split(' ')就能安全地切出单词数组。由于压力用例中没有前导/尾部分隔符,words中不会出现空串元素。

阶段二:逐词大小写规整。words.map((word, i) => ...)利用索引区分首词与其余词:

  • i === 0时直接word.toLowerCase(),对应规则 2;
  • 其余词用word.split('')拆成字符数组,shift()取出首字符并toUpperCase(),剩余字符join('')toLowerCase(),再拼接——对应规则 3。这里shift()的妙处在于首字符不参与「其余转小写」的逻辑,避免大小写处理重复或遗漏。

阶段三:拼接。join('')以空字符串连接所有词,分隔符在阶段一已经被替换掉,因此天然满足规则 4。

实现要点与常见错误

结合仓库内的测试用例与解法,实现时值得注意的要点有:

  1. 先归一化、再拆分。如果直接split单个字符(例如split(/[_\- ]/)),连续分隔符会产生空串元素,首词判断(i === 0)之后还会把空串当作「后续单词」处理,导致输出多出一个被大写的空串或大小写错位。
  2. 大小写处理要覆盖整词而非首字符之外的一小部分"FREE cODE cAMP"这类输入中,后续词的首字母可能本身已是小写(cODE),因此必须shift()toUpperCase(),而不能假设首字母已是小写。
  3. 首词也要完整小写"HELLO WORLD"中首词全大写,仅处理首字母大写/小写都不够,必须对整个首词调用toLowerCase()
  4. 等价写法:也可以用s.match(/[^_\- ]+/g)直接提取出「非分隔符」的单词序列,跳过显式 replace;但仓库给出的官方解法以 replace + split 为主干,语义上与题目「一个序列 = 一个边界」的表述逐字对应,可读性更贴近题面规则。

在仓库中复核本题

如果你在本仓库中查看或复核这道题,推荐的路径是:

  1. 阅读题目原文与全部用例:curriculum/challenges/english/blocks/daily-coding-challenges-javascript/6821ebd4237de8297eaee791.md;
  2. 确认它在课程块中的排序与编辑器配置:curriculum/structure/blocks/daily-coding-challenges-javascript.json;
  3. 确认challengeType: 28的语义(每日 JavaScript 挑战、语言映射、测试位置):packages/shared/src/config/challenge-types.ts;
  4. 了解每日挑战数据如何进入平台:tools/daily-challenges 的 seed 脚本说明,以及 api/src/daily-coding-challenge 中的查询路由说明。

把本文的解法粘贴进任意 Node 环境,运行题目中给出的 5 条assert.equal断言即可完整验证实现——这组断言同时也是该题在 freeCodeCamp 平台上的判分测试。

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 19:57:57

FPGA基带与中频处理实战:从DDC到同步环路的工程实现

1. 基带与中频处理:为什么FPGA是绕不开的一块硬骨头做通信、雷达、电子对抗这一类系统,如果你绕开基带和中频去谈FPGA,那基本就等于绕开了FPGA最核心的价值。我接触FPGA开发十年出头,从最开始的SPI控制器、接口逻辑,一…

作者头像 李华
网站建设 2026/9/8 19:54:11

降AI率工具哪个好用?亲测2026年8款免费降AI率工具

自己辛苦码字大半个月完成的稿件,被系统判定含有机器生成痕迹,这种感觉真的很无奈。为了找到靠谱的免费降ai率工具,我把市面上的主流产品逐一测试了一遍。 这段时间我经历过字数大幅增加的情况,也遇到了排版完全错乱的麻烦。今天就…

作者头像 李华
网站建设 2026/9/8 19:52:40

深度学习恶意软件检测实战:基于CNN的源码与数据集解析

简介:面向深度学习与信息安全交叉领域学习者,这份恶意软件检测项目提供完整源码与配套数据,可满足课程设计、毕业设计或入门基准项目的需要。压缩包内含163个文件,共34.66MB,其中18个Python脚本负责模型训练、预测与评…

作者头像 李华