按参数删除数组元素 (Drop it)
题目链接
问题解释
- 这个
function
接受一个数组参数arr
和一个函数参数func
。返回值为arr
第一个满足参数func
的元素及其之后的所有元素 - 如果
arr
是[1, 2, 3, 4]
,func
是function(n) {return n >=3;}
,那么此时返回值应为[3, 4]
- 更值得关注的是这样的情况,如果
arr
是[0, 1, 0, 1]
,func
是function(n) {return n === 1;}
,那么此时返回值应为[1, 0, 1]
基本解法
思路提示
- 这道题目和上一道 Finders Keepers 的基本思路很相似,难度也很低。区别仅仅在于 Finders Keepers 需要返回一个元素,这道题是返回一个数组
- 题目说明中提到,这道题可以用到
Array.shift()
。尽管我觉得不是很必要,但我们还是先来看看如何用这个方法以及循环写
参考链接
代码
1 | function drop(arr, func) { |
解释
- 首先,这里需要存一份原数组的深拷贝。深拷贝的意思是,就算原数组修改,这份拷贝也不会被影响。你可以执行一下这段代码,来比较一下深拷贝 (Hard Copy, Deep Copy) 与浅拷贝 (Shallow Copy) 的区别
1 | var arr = [1, 2, 3, 4]; |
- 不难看出,其中
shallowCopy
会变化,而hardCopy
不会变 - 至于为什么需要存一份深拷贝,原因很简单。我们在移除数组元素的时候,会使整个数组的长度变短。相当于,如果第一个元素被移除了,而我们又执行了
i++
,那就会跳过原数组中第二个元素的判断,直接去判断原数组中的第三个了 - 如果我们存了一份拷贝,那么我们循环的参考依然是原来的那个
arr
,而执行删除元素的是那份深拷贝,因此互相之间是不会有任何影响的 - 顺便,深拷贝的方式有很多,我们也可以新建一个空数组,然后遍历
arr
,然后把其中的每个元素push
到新建数组中。以下再列举六种深拷贝数组的方式:
1 | var arr = [1, 2, 3, 4]; |
- 多说一句,其实有些方法是有适用条件的。我个人比较喜欢用
arr.slice()
,但这种只适用于arr
中都是Primitive Type
(原始类型) 元素的情况 - 当然,除了存一份拷贝,我们还有其他方式去解决,比如,删除元素的时候执行以下
i--
可以是一种做法;再比如,从右边遍历也可以是一种做法。有兴趣的朋友可以自己写一下试试 - 最后需要单独返回一下
[]
。因为如果所有元素都不满足func
,则应该返回[]
推荐写法
思路提示
- 题目还给出了使用
Array.slice
方法的提示。我们来看一看如何用这个方法解题 - 对于这道题目,关键就在于如何找到第一个使得测试函数
func
返回值为true
的元素。只要找到了,我们只需要用一下slice
,一直截取到数组终点就可以了
参考链接
代码
1 | function drop(arr, func) { |
解释
- 跟前一种思路类似。但这里,我们不再需要存储数组的拷贝,也不需要再执行删除元素操作
- 这里的思路是,我们去找到第一个使得
func
返回true
的元素的index
(索引),然后直接slice
一下就可以了。slice
方法如果只传入一个参数,那么就会一直截取到结尾