ARTICLE DETAIL

资讯详情

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

Modern JavaScript Tutorial 精讲:用 splice 实现数组区间过滤 filterRangeInPlace(原地修改)

Modern JavaScript Tutorial 精讲:用 splice 实现数组区间过滤 filterRangeInPlace(原地修改) 文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载导读本文围绕 Modern JavaScript Tutorialen.javascript.info 仓库 中数组方法Array methods一节的经典习题Filter range in place展开。题目要求编写filterRangeInPlace(arr, a, b)在不新建数组的前提下从原数组中移除所有不在闭区间[a, b]内的元素并且函数不返回任何值。读完本文你将掌握如何利用splice在正向遍历中安全删除元素、为什么删除后要手动执行i--、它与基于filter的非破坏性版本filterRange的本质区别以及仓库中配套的 Mocha 测试如何验证正确性。一、题目回顾原地过滤的完整定义原题出自 task.md题目难度标记为importance: 4中等偏上核心要求如下编写函数filterRangeInPlace(arr, a, b)接收数组arr移除其中所有不在a与b之间的值。判定条件是a ≤ arr[i] ≤ b。 函数只能修改传入的数组不能返回任何东西。示例行为let arr [5, 3, 8, 1]; filterRangeInPlace(arr, 1, 4); // 移除 1 到 4 之外的数字 alert( arr ); // [3, 1]从示例可以看到两个关键约束原地修改in placearr自身被改变调用后只剩下区间内的元素[3, 1]无返回值函数修改的是外部传入的数组引用因此无需也不应该返回新数组。这一约束与同章节的姊妹题 Filter range非原地版 形成鲜明对照filterRange要求不修改数组、返回新数组而filterRangeInPlace则要求修改原数组、不返回任何东西。这两题组合起来恰好覆盖了 JavaScript 中变换数组的两种基本范式新建并返回与就地改写。二、参考解法逐行拆解仓库给出的标准解答位于 solution.md运行版源码见 _js.view/solution.jsfunction filterRangeInPlace(arr, a, b) { for (let i 0; i arr.length; i) { let val arr[i]; // remove if outside of the interval if (val a || val b) { arr.splice(i, 1); i--; } } } let arr [5, 3, 8, 1]; filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4 alert( arr ); // [3, 1]2.1 判定条件取反写法区间保留条件是a ≤ val ≤ b代码中直接使用其否定形式if (val a || val b) {即小于下界或大于上界的元素就是要被删除的元素。这里刻意用||连接两个越界方向而非!(val a val b)语义上等价但先写出删除条件会让阅读者更直观地理解循环体的动作。非破坏性版本 2-filter-range/solution.md 则采用保留写法并加括号提升可读性return arr.filter(item (a item item b));两种写法互为镜像正好对应删掉越界的与留下区间的两种视角。2.2 删除机制splice 而非 delete删除数组元素时本章正文Array methods 的splice一节特别强调直接使用delete arr[i]只会把该位置的值置为undefined数组长度不变留下空洞而splice(i, 1)会真正移除该元素并把后续所有元素前移补齐数组长度减一。splice的完整语法为arr.splice(start[, deleteCount, elem1, ..., elemN])它从start索引开始删除deleteCount个元素可再插入新元素并返回被删除元素组成的数组。本解法每次只删除 1 个元素因此写为arr.splice(i, 1)返回的被删数组此处不使用。2.3 核心难点删除后索引回退i--这是本解法最值得反复咀嚼的一行。正向for循环遍历时一旦在索引i处执行splice(i, 1)原本位于i1的元素会整体左移一位顶替到位置i。如果此时不做处理for循环的i会让下一个迭代跳过这个顶替上来的元素造成漏检。因此代码在删除后立刻执行i--;与循环末尾的i抵消使下一轮迭代仍停留在原位置检查刚左移过来的元素。以arr [5, 3, 8, 1]、区间[1, 4]为例迭代i当前数组元素是否越界动作数组变化10[5, 3, 8, 1]5是5 4splice(0,1); i--[3, 8, 1]20[3, 8, 1]3否1 ≤ 3 ≤ 4跳过[3, 8, 1]31[3, 8, 1]8是8 4splice(1,1); i--[3, 1]41[3, 1]1否1 ≤ 1 ≤ 4跳过[3, 1]可见正是i--保证了左移元素如第二次迭代中的 8不会被漏掉最终得到[3, 1]与题目示例完全一致。2.4 为什么函数不写 return由于数组是引用类型arr.splice(...)的修改直接作用于调用者传入的同一个数组对象。函数体结束后外部变量arr已经指向被改写后的数组因此函数无需、也不应返回新值。若画蛇添足地返回新数组反而违背题目only modify the array的约束也容易让调用方误以为原数组未被修改。三、测试用例验证仓库如何保证正确性仓库为每个习题都配套了可运行的 Mocha 测试本习题的测试位于 _js.view/test.jsdescribe(filterRangeInPlace, function() { it(returns the filtered values, function() { let arr [5, 3, 8, 1]; filterRangeInPlace(arr, 2, 5); assert.deepEqual(arr, [5, 3]); }); it(doesnt return anything, function() { assert.isUndefined(filterRangeInPlace([1,2,3], 1, 4)); }); });两条用例精确对应题目的两个硬性要求原地过滤生效对[5, 3, 8, 1]调用filterRangeInPlace(arr, 2, 5)后用assert.deepEqual断言arr变为[5, 3]深比较确保数组内容与顺序都正确无返回值assert.isUndefined(...)断言函数调用的返回值为undefined防止有人写出返回新数组的偏离实现。这两个断言从行为层面完整锁定了修改原数组 不返回值的契约是理解本习题意图最直接的佐证。四、与非原地版本 filterRange 的对比与选型本习题与 Filter range 互为对照这里汇总两者差异维度filterRange非原地filterRangeInPlace原地实现核心arr.filter(item a item item b)循环 arr.splice(i, 1)i--是否修改原数组否是返回值新数组无undefined适用场景需要保留原始数据做后续对比/回溯数据量大或仅需保留区间内数据节省内存与拷贝开销时间复杂度O(n)新数组构建O(n·m)每次 splice 触发元素前移最坏为 O(n²)从性能上看filter版本只需一次线性扫描并拷贝符合条件的元素而splice每次删除都会让后续元素左移连续大量删除时会有额外的元素搬运成本。因此原地版本的价值在于空间与引用语义不产生新数组、调用方持有的引用即最终结果而非性能优势。当数组中大部分元素都需要删除、且对性能敏感时更推荐的做法是先标记、后单次重排或直接改用filter配合重新赋值arr.length这些是超出本题范围的工程化延伸。五、延伸讨论遍历中删除元素的一般规律filterRangeInPlace展示的i--技巧是边遍历边删除类问题的通用范式。与之配套的常见替代方案包括倒序遍历从末尾向开头for (let i arr.length - 1; i 0; i--)删除i位置的元素不影响前面尚未访问的索引可以省去i--代码更不易出错先收集再批量处理遍历中只记录待删索引结束后统一处理避免频繁触发元素搬移filter 重赋值arr arr.filter(...)或arr.splice(0, arr.length, ...filtered)用函数式风格表达原地替换意图。本教程选择的splice i--正向遍历胜在把数组元素在删除后会左移这个底层机制直接暴露给读者是理解数组内存布局的最佳教学案例。相关splice的完整语法、负索引支持与插入/替换能力均可继续查阅 Array methods 正文 的splice一节其中还包含delete与splice行为差异的详细演示。总结filterRangeInPlace这道习题的价值不在算法复杂度而在于三点其一明确了闭区间[a, b]内保留、越界删除的判定条件及其取反写法其二演示了splice(i, 1)作为真正的元素删除手段与delete的本质区别其三通过i--揭示了正向遍历中删除元素后索引错位的经典陷阱。配合 solution.md、test.js 与 filterRange 对照实现读者既能获得可运行的完整代码也能从测试用例中反推题目的行为契约从而真正掌握原地修改数组这一 JavaScript 日常开发中的高频技能。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐json-render 中 Remotion Composition 的定义与动态元数据从 Root.tsx 到 Timeline Specjson render 中 Remotion Composition 的定义与动态元数据从 Root.tsx 到 Timeline Spec 本文围绕 ski文档/教程前端JavaScript 循环与标签实战输出区间素数的经典练习Modern JavaScript Tutorial 精讲JavaScript 循环与标签实战输出区间素数的经典练习Modern JavaScript Tutorial 精讲 本指南围绕 Modern JavaS文档/教程前端Modern JavaScript Tutorial 区间判断实战用 实现 14~90 闭区间检查Modern JavaScript Tutorial 区间判断实战用 实现 14~90 闭区间检查 导读 在 JavaScript 的第一阶段入门教程《文档/教程前端上一篇ElectronBot 3D打印故障排除翘边、层间分离与堵头解决下一篇POCO C库进程间通信完整指南跨平台IPC实战教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表