-
Notifications
You must be signed in to change notification settings - Fork 1.4k
drop it
S1ngS1ng edited this page Jul 9, 2017
·
1 revision
- 这个
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()。尽管我觉得不是很必要,但我们还是先来看看如何用这个方法以及循环写
function drop(arr, func) {
var arrCopy = arr.slice();
for (var i = 0; i < arr.length; i++) {
if(!func(arr[i])) {
arrCopy.shift();
} else {
return arrCopy;
}
}
return [];
}- 首先,这里需要存一份原数组的深拷贝。深拷贝的意思是,就算原数组修改,这份拷贝也不会被影响。你可以执行一下这段代码,来比较一下深拷贝 (Hard Copy, Deep Copy) 与浅拷贝 (Shallow Copy) 的区别
var arr = [1, 2, 3, 4];
var shallowCopy = arr;
var hardCopy = arr.slice();
arr.shift();
console.log(shallowCopy, hardCopy);- 不难看出,其中
shallowCopy会变化,而hardCopy不会变 - 至于为什么需要存一份深拷贝,原因很简单。我们在移除数组元素的时候,会使整个数组的长度变短。相当于,如果第一个元素被移除了,而我们又执行了
i++,那就会跳过原数组中第二个元素的判断,直接去判断原数组中的第三个了 - 如果我们存了一份拷贝,那么我们循环的参考依然是原来的那个
arr,而执行删除元素的是那份深拷贝,因此互相之间是不会有任何影响的 - 顺便,深拷贝的方式有很多,我们也可以新建一个空数组,然后遍历
arr,然后把其中的每个元素push到新建数组中。以下再列举六种深拷贝数组的方式:
var arr = [1, 2, 3, 4];
// ES5
var hardCopy1 = arr.slice();
var hardCopy2 = arr.concat();
var hardCopy3 = [].concat(arr);
var hardCopy4 = JSON.parse(JSON.stringify(arr));
// ES6
var hardCopy5 = Array.from(arr);
var hardCopy6 = [...arr];- 多说一句,其实有些方法是有适用条件的。我个人比较喜欢用
arr.slice(),但这种只适用于arr中都是Primitive Type(原始类型) 元素的情况 - 当然,除了存一份拷贝,我们还有其他方式去解决,比如,删除元素的时候执行以下
i--可以是一种做法;再比如,从右边遍历也可以是一种做法。有兴趣的朋友可以自己写一下试试 - 最后需要单独返回一下
[]。因为如果所有元素都不满足func,则应该返回[]
- 题目还给出了使用
Array.slice方法的提示。我们来看一看如何用这个方法解题 - 对于这道题目,关键就在于如何找到第一个使得测试函数
func返回值为true的元素。只要找到了,我们只需要用一下slice,一直截取到数组终点就可以了
function drop(arr, func) {
for (var i = 0; i < arr.length; i++) {
if (func(arr[i])) {
return arr.slice(i);
}
}
return [];
}- 跟前一种思路类似。但这里,我们不再需要存储数组的拷贝,也不需要再执行删除元素操作
- 这里的思路是,我们去找到第一个使得
func返回true的元素的index(索引),然后直接slice一下就可以了。slice方法如果只传入一个参数,那么就会一直截取到结尾