首页
/ freeCodeCamp 每日编程挑战第 310 题「British to American」:英式拼写转美式拼写的字符串替换完整解法

freeCodeCamp 每日编程挑战第 310 题「British to American」:英式拼写转美式拼写的字符串替换完整解法

2026-09-09 09:17:15作者:申梦珏Efrain

本篇技术指南围绕 freeCodeCamp 开源课程中 Daily Coding Challenge 第 310 题(Challenge 310: British to American)展开,完整解析题目要求、13 条英式/美式拼写对照表、大小写不敏感与派生词两条隐藏规则,并逐行剖析官方参考解法中基于正则与 replace 回调的替换原理。读者阅读本文后将掌握"基于映射表 + 全局忽略大小写正则 + 首字母大小写还原回调"这一类字符串规范化问题的通用解法,并了解该挑战在 freeCodeCamp 仓库中的题目组织、API 下发与数据库播种机制。

一、挑战定位:Daily Coding Challenge 生态中的一道字符串处理题

Challenge 310「British to American」是 freeCodeCamp 课程体系中 daily-coding-challenges-javascript 区块的成员。该区块共规划 365 道挑战(对应全年每日一题),每道题同时提供 JavaScript 与 Python 两个语言的实现与测试。Challenge 310 在区块中的登记记录位于 区块结构清单id: 6a151d32d772271dd2448c2ctitle: "Challenge 310: British to American"),其 challengeType 为 28(每日挑战类型)。

从仓库的实际运转机制可以了解这道题所处的完整链路:

Challenge 310 正是在"按日期下发题目 → 用户在前端每日挑战界面作答 → 测试用例自动判定"这一机制中被消费的一环。而本文聚焦的,是这道题本身的算法内核:用一张固定映射表完成英式拼写到美式拼写的文本规范化

二、题目要求全解:13 条对照表与两条关键规则

原题描述如下:给定一个句子,依据下方查找表,将其中所有英式英语拼写转换为对应的美式英语拼写,并返回更新后的句子。

完整对照表(原文 13 条,一条不少):

英式拼写 美式拼写
"colour" "color"
"flavour" "flavor"
"honour" "honor"
"neighbour" "neighbor"
"labour" "labor"
"humour" "humor"
"centre" "center"
"fibre" "fiber"
"defence" "defense"
"offence" "offense"
"organise" "organize"
"recognise" "recognize"
"analyse" "analyze"

对照表覆盖了英语拼写差异的几大经典类别:-our → -or(colour/flavour/honour/neighbour/labour/humour)、-re → -er(centre/fibre)、-ce → -se(defence/offence)、-ise → -ize(organise/recognise/analyse)。理解这些词族规律有助于举一反三:即使将来映射表扩充,替换策略本身无需改变。

在对照表之外,题目还明确规定了两条容易被忽略的规则,它们是本题真正的考点:

  1. 替换必须大小写不敏感:例如 "Colour"(句首大写)应转换为 "Color",而不是小写的 "color" 或漏掉不转换。
  2. 派生词也要跟着变:输入中可能包含以表中词根为基础扩展出的单词,同样需要转换。题目给出的两个显式例子:
    • "colouring""coloring"(词根 colour + 后缀 -ing
    • "disorganised""disorganized"(前缀 dis- + 词根 organise + 后缀 -d

三、测试用例逐条拆解:从单词替换到复合句式

原题提供了 5 组测试断言(全部使用 assert.equal 做严格相等比较),它们是判定实现正确与否的唯一标准。逐条拆解如下:

用例 1:简单单数替换

assert.equal(britishToAmerican("I love the colour blue."), "I love the color blue.");

仅含一个命中词 colour,验证最基础的单次替换。

用例 2:-re → -er 词族

assert.equal(britishToAmerican("The fibre optic cable is new."), "The fiber optic cable is new.");

验证 fibre → fiber,且替换不影响句中其他单词。

用例 3:多个词同句命中 + 词族交叉

assert.equal(
  britishToAmerican("It's an honour to meet someone with such humour."),
  "It's an honor to meet someone with such humor."
);

honourhumour 同时出现在一个句子中,验证多次替换的累积效果,且 honour 前是冠词 an,替换结果 honor 不影响冠词本身。

用例 4:大写还原 + 派生词 + 多词组合

assert.equal(
  britishToAmerican("The unrecognised artist analysed his colour palette at the centre."),
  "The unrecognized artist analyzed his color palette at the center."
);

这一条同时检验三条核心能力:

  • unrecognisedunrecognized:派生词(前缀 un- + 词根 recognise);
  • analysedanalyzed:派生词(词根 analyse + 后缀 -d);
  • colourcentre:普通单次替换。

用例 5:压力测试——近乎全词表的大句子

assert.equal(
  britishToAmerican("The offence analysed, with organisation, the defence centre and recognised that the neighbouring labouror was humourous, flavourful, and colourful."),
  "The offense analyzed, with organisation, the defense center and recognized that the neighboring laboror was humorous, flavorful, and colorful."
);

这是最刁钻的一条,隐藏着三个关键细节:

  • neighbouringneighboring:词根 neighbour + 后缀 -ing
  • humouroushumorous:词根 humour + 后缀 -ous,替换后变成 humor + ous = humorous
  • organisation 保持不变:因为对照表中没有 organise 的派生路径能匹配 organisation(其词干是 organis,不含 organise 这一连续子串),所以原句中的 organisation 被原样保留——注意预期输出中它没有被改成 organization

四、官方参考解法逐行剖析

题目的种子代码(# --seed--)为:

function britishToAmerican(sentence) {

  return sentence;
}

种子函数接受一个字符串参数并直接原样返回,全部逻辑需要由解题者补充。官方参考解法(# --solutions--)完整如下:

function britishToAmerican(sentence) {
  const lookup = {
    colour: "color",
    flavour: "flavor",
    honour: "honor",
    neighbour: "neighbor",
    labour: "labor",
    humour: "humor",
    centre: "center",
    fibre: "fiber",
    defence: "defense",
    offence: "offense",
    organise: "organize",
    recognise: "recognize",
    analyse: "analyze"
  };

  let result = sentence;

  for (const [british, american] of Object.entries(lookup)) {
    const regex = new RegExp(british, "gi");
    result = result.replace(regex, match => {
      return match[0] === match[0].toUpperCase()
        ? american[0].toUpperCase() + american.slice(1)
        : american;
    });
  }

  return result;
}

这套解法由三个层次构成,每一层都精准对题目要求:

第一层:映射表数据结构(lookup 对象) 13 条英式拼写作为键、美式拼写作为值。由于键名都是合法 JavaScript 标识符(纯字母),可以直接使用对象字面量而非 MapObject.entries() 按对象属性插入顺序返回键值对数组,因此替换顺序与表中排列顺序一致——在本数据集中各词根互不包含(除了单词内部的公共后缀如 -our),替换顺序不会造成冲突,但仍建议保持表序以提升可读性。

第二层:子串匹配而非单词匹配(new RegExp(british, "gi") 这是整个解法中最关键也最容易被误解的设计决策。正则没有使用词边界锚点 \b,而是以 "gi" 标志做"全局 + 忽略大小写"的子串匹配:

  • g(global):替换句子中所有出现的该词根,而不是只替换第一个;
  • i(ignoreCase):让 colour 能同时命中 ColourCOLOURColoUr 等各种大小写形态,满足"替换应大小写不敏感"的规则一;
  • 不加 \b:使得 colouring(内含 colour)、disorganised(内含 organise)、neighbouring(内含 neighbour)、humourous(内含 humour)这类派生词也能被命中,满足"基于词根的派生词也要转换"的规则二。

正因如此,解法才能在不显式枚举任何派生词的情况下,仅凭 13 个词根覆盖测试中出现的全部变体。需要指出的是,这种"无边界子串替换"是有意为之的取舍:它也会把任何意外包含该子串的单词一并替换(例如一个自定义专有名词恰好含 centre),但在本题目限定场景下,这正是实现规则二的最简手段。

第三层:replace 回调中的大小写还原

result = result.replace(regex, match => {
  return match[0] === match[0].toUpperCase()
    ? american[0].toUpperCase() + american.slice(1)
    : american;
});

回调函数的参数 match 是被命中的实际文本(保留了原文的大小写形态)。通过判断 match[0] === match[0].toUpperCase() 来识别"首字母是否为大写":

  • 若首字母大写(如 Colour),则返回美式词的首字母大写 + 剩余部分("Color");
  • 否则返回完整小写美式词("color")。

这个判断对全大写场景同样成立(COLOUR 的首字母 C 是大写,会得到 COLOR 的映射逻辑下的 "Color"),虽然原题测试未覆盖全大写输入,但该写法天然兼容。由于 replace 对每个匹配独立调用回调,同一句子中大小写混合出现(如 Colourcolour 并存)也能各自得到正确还原。

五、边界情况与易错点总结

结合测试用例与解法,可以提炼出本题的四个关键易错点:

易错点 说明 错误示范 正确做法
忘记大小写不敏感 只用 replace(british, american)Colour 无法命中 "Colour".replace(/colour/, "color") 无效果 正则加 i 标志
只替换第一个命中 忘了 g 标志 多词句只改第一处 正则加 g 标志
用了词边界 \b 派生词被排除在外 /\bcolour\b/ 匹配不到 colouring 去掉 \b,做子串匹配
直接整体替换丢失大写 replace(regex, american)Colour 变成小写 color 用例 4 断言失败 用回调按命中文本首字母还原大小写

另外两个值得注意的细节:

  1. organisation 这类"差一个字母"的陷阱词organisationorganis 但不含 organise,因此不会被转换。如果题目要求把 organisation 也转成 organization,就需要额外补充词根或更复杂的规则;本题对照表没有它,所以保持原样才是正确输出。
  2. 派生词的正确性依赖"替换结果 + 后缀拼接"恰好拼出合法美式词humour + oushumorousneighbour + ingneighboringanalyse + danalyzed,这些拼接之所以成立,是因为 -our → -or-re → -er-ise → -ize 的转换只作用于词根字母,不影响附加后缀。如果某个派生规则会改变词根尾字母(例如 y → i 类变换),则子串替换策略需要另行扩展。

六、延伸:挑战数据如何被验证与下发

Challenge 310 的测试用例并非只在课程文件中静态存在。从仓库实现可以梳理出它的完整生命周期:

  • 定义阶段:题目 Markdown 中的 --hints-- 小节定义了判定用的测试字符串(即上文 5 组 assert.equal),--seed-contents-- 给出用户作答起点,--solutions-- 给出参考答案;区块结构清单 daily-coding-challenges-javascript.json 登记了挑战 id 与标题。
  • 播种阶段seed-daily-challenges.ts 从课程中拉取挑战并按天写入数据库,脚本内置了 365 道的数量校验与固定起始日期(2025-08-11)的防误改保护。
  • 下发阶段:API 的 daily-coding-challenge 路由 通过 Prisma 查询 dailyCodingChallenges 表,按日期返回挑战详情,且"不返回晚于今天(美国中部时间)的挑战";响应的 descriptiontestschallengeFiles 结构由 类型定义 约束,客户端还会用 daily-coding-challenge-validator.ts 中的 Joi 校验器对响应做二次校验。
  • 作答阶段:前端 每日挑战小组件 提供"今日挑战"与"历史归档"入口,用户写出 britishToAmerican 后由测试框架逐条执行 --hints-- 中的断言判定通过与否。

七、总结

Challenge 310「British to American」是一个典型的"映射表 + 文本规范化"问题,但它的两个隐藏规则——大小写不敏感、派生词连带替换——把难度从简单的查表提升到了对正则匹配语义的准确理解上。官方解法的精髓在于刻意省略词边界 \b,用无边界子串匹配一次性解决所有派生词形态,再借助 replace 回调按命中文本首字母还原大小写。这一组合技巧同样适用于拼写纠错、术语统一、地区化文案适配等真实场景:只要把 lookup 换成任意键值映射表,函数骨架即可直接复用,是值得沉淀为模板的通用字符串处理范式。

掌握这道题后,读者不妨进一步研究仓库中同区块的相邻挑战(如 Challenge 311: SpellcasterChallenge 114: Camel to Snake),它们在字符串变换思路上与本题目一脉相承。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525