// 方法1 双层循环
// var array = [1,1,"1","1"];
// function unique(array) {
// // res用来存储结果
// var res = [];
// for(var i = 0; i < array.length; i++) {
// for(var j = 0; j < res.length; j++) {
// if(array[i] === res[j]) {
// break;
// }
// }
// // 如果array[i]是惟一的,那么执行完循环,j等于res.length
// if(j === res.length) {
// res.push(array[i])
// }
// }
// return res;
// }
// console.log(unique(array)); //[1,"1"]
// 在这个方法中使用循环嵌套,最外层循环array,里面循环res,如果array[i]的值跟res[j]的值相等,就跳出循环;如果不等于就说明元素是惟一的,这时候j的值就会等于res的长度,根据这个特点进行判断,将值添加进res
// 方法2 indexOf -1
// 使用indexOf可以简化内层循环
// var array = [2,2,"2","2"];
// function unique(array) {
// var res = [];
// for(var i = 0; i < array.length; i++) {
// var current = array[i];
// if(res.indexOf(current) === -1) {
// res.push(current)
// }
// }
// return res;
// }
// console.log(unique(array)); //[2,"2"]
// 方法3 ES6
// 可以使用Set和Map数据结构,以Set为例,ES6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值
// Set
// var array = [3,3,"3","3"];
// function unique(array) {
// return Array.from(new Set(array));
// }
// console.log(unique(array)); //[3,"3"]
// 可以简化为:
// function unique(array) {
// return [...new Set(array)];
// }
// console.log(unique(array)); //[3,"3"]
// 还可以简化为:
// var unique = (a) => [...new Set(a)]
// Map
// var array = [3,3,"3","3"];
// function unique(array) {
// const seen = new Map()
// return array.filter((a) => !seen.has(a) && seen.set(a,1))
// }
// console.log(unique(array)); //[3,"3"]
// 方法4 排序后去重
// 先将要去重的数组使用sort方法排序后,相同的值会被排在一起,然后就可以只判断当前元素与上一个元素知否相同,相同就说明重复,不相同就添加进res
// var array = [4,4,"4","4"];
// function unique(array) {
// var res = [];
// var sortedArray = array.concat().sort();
// var seen;
// for(var i = 0; i < sortedArray.length; i++) {
// if(!i || seen !== sortedArray[i]) {
// res.push(sortedArray[i]);
// }
// seen = sortedArray[i];
// }
// return res;
// }
// console.log(unique(array)); //[4,"4"]
// 如果对一个已经排好序的数组去重,这种方法的效率高于indexOf
// 方法5 filter
// 使用此方法来简化外层循环
// var array = [5,5,"5","5"];
// function unique(array) {
// var res = array.filter(function(item,index,array) {
// return array.indexOf(item) === index;
// })
// return res;
// }
// console.log(unique(array)); //[5,"5"]
// 排序去重的方法:
// var array = [5,5,"5","5"];
// function unique(array) {
// return array.concat().sort().filter(function(item,index,array) {
// return !index || item !== array[index -1]
// })
// }
// console.log(unique(array));
// 方法6 Object键值对
// 这种方法是利用一个空的 Object 对象,我们把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。示例代码如下:
// var array = [1, 2, 1, 1, '1'];
// function unique(array) {
// var obj = {};
// return array.filter(function(item, index, array){
// return obj.hasOwnProperty(item) ? false : (obj[item] = true)
// })
// }
// console.log(unique(array)); // [1, 2]
// 我们可以发现,是有问题的,因为 1 和 '1' 是不同的,但是这种方法会判断为同一个值,这是因为对象的键值只能是字符串,所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题:
// var array = [1, 2, 1, 1, '1'];
// function unique(array) {
// var obj = {};
// return array.filter(function(item, index, array){
// return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
// })
// }
// console.log(unique(array)); // [1, 2, "1"]
// 然而,即便如此,我们依然无法正确区分出两个对象,比如 {value: 1} 和 {value: 2},因为 typeof item + item 的结果都会是 object[object Object],不过我们可以使用 JSON.stringify 将对象序列化:
// var array = [{value: 1}, {value: 1}, {value: 2}];
// function unique(array) {
// var obj = {};
// return array.filter(function(item, index, array){
// console.log(typeof item + JSON.stringify(item))
// return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
// })
// }
// console.log(unique(array)); // [{value: 1}, {value: 2}]
// 方法7 unique API
// 写一个名为 unique 的工具函数,根据一个参数 isSorted 判断传入的数组是否是已排序的,如果为 true,就判断相邻元素是否相同,如果为 false,就使用 indexOf 进行判断
// var array1 = [1, 2, '1', 2, 1];
// var array2 = [1, 1, '1', 2, 2];
// // 第一版
// function unique(array, isSorted) {
// var res = [];
// var seen = [];
// for (var i = 0, len = array.length; i < len; i++) {
// var value = array[i];
// if (isSorted) {
// if (!i || seen !== value) {
// res.push(value)
// }
// seen = value;
// }
// else if (res.indexOf(value) === -1) {
// res.push(value);
// }
// }
// return res;
// }
// console.log(unique(array1)); // [1, 2, "1"]
// console.log(unique(array2, true)); // [1, "1", 2]
// 优化
// 新需求:字母的大小写视为一致,比如'a'和'A',保留一个就可以了!
// 虽然可以先处理数组中的所有数据,比如将所有的字母转成小写,然后再传入unique函数,但是有没有方法可以省掉处理数组的这一遍循环,直接就在去重的循环中做呢?
// var array3 = [1, 1, 'a', 'A', 2, 2];
// // 第二版
// // iteratee 英文释义:迭代 重复
// function unique(array, isSorted, iteratee) {
// var res = [];
// var seen = [];
// for (var i = 0, len = array.length; i < len; i++) {
// var value = array[i];
// var computed = iteratee ? iteratee(value, i, array) : value;
// if (isSorted) {
// if (!i || seen !== computed) {
// res.push(value)
// }
// seen = computed;
// }
// else if (iteratee) {
// if (seen.indexOf(computed) === -1) {
// seen.push(computed);
// res.push(value);
// }
// }
// else if (res.indexOf(value) === -1) {
// res.push(value);
// }
// }
// return res;
// }
// console.log(unique(array3, false, function(item){
// return typeof item == 'string' ? item.toLowerCase() : item
// })); // [1, "a", 2]
// 在这一版也是最后一版的实现中,函数传递三个参数:
// array:表示要去重的数组,必填
// isSorted:表示函数传入的数组是否已排过序,如果为 true,将会采用更快的方法进行去重
// iteratee:传入一个函数,可以对每个元素进行重新的计算,然后根据处理的结果进行去重