手写实现数组去重方法。
一般这样的面试题还要求的不止一种方法实现,这就需要充分考虑数组的使用了。
方法一: 使用ES6中的 Set() 方法
Set()是ES6提供的新的数据结构,其类似于数组,但是成员值都是唯一的,没有重复的值。利用这一特性,完成数组的去重操作。这里需要注意的是返回值也是类数组的 Set数据结构,需要转换成数组结构。
// 这里使用扩展运算符 ... 讲 Set 结构数据转换成数组
var delRepetition = function (arr) {
return [...new Set(arr)];
}
// 也可以使用 ES6 中的 Array.from() 转换成数组
var delRepetition = function (arr) {
return Array.from(new Set(arr));
}
使用该方法比较的直观容易理解,唯一需要注意的是兼容性即可。
参考资料: ESMAScript 6 入门
方法二:使用内置函数
Array内置函数中提供数组元素的查询:
Array.prototype.indexOf()搜索数组元素,并返回所在的位置,未找到返回 -1;
Array.prototype.includes()判断数组是否包含指定的值,包含返回 true,不包含返回 false;
判断当先元素的下标是否等于查询结果的下标,如果是,则表示第一次出现,如果非表示重复出现。可以借助于Array.prototype.filter()函数返回新的数组内容。
// 如果下标为当前元素下标,表示第一次出现
// 可以直接放入新的数组当中
var delRepetition = function (arr) {
let isN = false;
let newArr = arr.filter((currentValue, index, array) => {
// 判断当前元素是否为 NaN
// 可根据自己的需要删减
if (currentValue !== currentValue) isN = true;
return array.indexOf(currentValue) === index
})
// 如果包含有NaN元素,最后在添加上
if (isN) {
newArr.push(NaN);
}
return newArr;
}
该方法中包含了特殊类型 NaN 的检测,利用其自身不等于自身的特性进行检测,如果值中包含有NaN元素,最后添加到数组当中。
当然也可以直接利用数组从左向右计算的特性,返回最后的结果。原理都差不多,返回新数组。
var delRepetition = function (arr) {
let isN = false;
let newArr = arr.reduce((total, currentValue) => {
if (currentValue !== currentValue) {
isN = true;
} else {
total.indexOf(currentValue) === -1 && total.push(currentValue);
}
return total;
}, []);
if (isN) newArr.push(NaN);
return newArr;
}
方法三:新数组元素查询
查询元素是否存在需要进行循环遍历,可以使用 Array.prototype.forEach() 或 for ... of 等。也可以使用 for 循环 ,但是需要注意他们之间的区别,虚数组与实数组之间的转换。
使用数组的内置函数,查询新数组中是否包含有当前元素,如果不包含当前元素,则添加到新的数组当中,如果包含则跳过,这里需要摘出NaN。
var delRepetition = function (arr) {
let newArr = [],
isN = false;
for (let v of arr) {
if (v !== v) {
isN = true;
continue;
}
if (!newArr.includes(v)) {
newArr.push(v);
}
}
if (isN) newArr.push(NaN);
return newArr;
}
方法四:排序
先对元素排序,然后再对比插入:
var delRepetition = function (arr) {
let sArr = [].concat(arr).sort();
let newArr = [],
isN = false;
sArr.forEach((value, index, cArr) => {
if (value !== value) {
isN = true;
} else if (index === 0 || value !== cArr[index - 1]) {
// 如果是第一项,则直接插入
// 后一项不等于前一项,则插入后一项内容
newArr.push(value);
}
});
if (isN) newArr.push(NaN);
return newArr;
}
以上方法都进行过实际测试,测试的内容如下,返回结果除元素顺序不一致外,其他雷同。
delRepetition([
1, '1', 2, null, null, undefined, undefined,
'undefined', NaN, , NaN, 'NaN', 'null', 'true',
true, true, false, , false, 'false', ' ', '' ]);
// => [1, "1", 2, null, undefined, "undefined", NaN, "NaN", "null", "true", true, false, "false", " ", ""]
在这里有从网上借鉴了几个比较好的点,如算数运算符的使用 total.indexOf(currentValue) === -1 && total.push(currentValue);这里就利用了 && (和)运算符的特性,如果第一个条件不满足则不会运行第二个条件。