YvetteLau / Step-By-Step

不积跬步,无以至千里;
704 stars 66 forks source link

实现一个数组去重的方法 #31

Open YvetteLau opened 5 years ago

tpxiang commented 5 years ago

1、ES6中新增了数据类型set,set的一个最大的特点就是数据不重复。Set函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重。 function unique(arr) {

if (!Array.isArray(arr)) {
    console.log('type error!')
    return
}
return [...new Set(arr)]

} 2、数组的indexOf()方法可返回某个指定的元素在数组中首次出现的位置。该方法首先定义一个空数组res,然后调用indexOf方法对原来的数组进行遍历判断,如果元素不在res中,则将其push进res中,最后将res返回即可获得去重的数组。 function unique(arr) {

if (!Array.isArray(arr)) {
    console.log('type error!')
    return
}
let res = []
for (let i = 0; i < arr.length; i++) {
    if (res.indexOf(arr[i]) === -1) {
        res.push(arr[i])
    }
}
return res

} 3、创建空对象,遍历数组,将数组中的值设为对象的属性,并给该属性赋初始值1,每出现一次,对应的属性值增加1,这样,属性值对应的就是该元素出现的次数了。 function unique(arr) {

if (!Array.isArray(arr)) {
    console.log('type error!')
    return
}
let res = [],
    obj = {}
for (let i = 0; i < arr.length; i++) {
    if (!obj[arr[i]]) {
        res.push(arr[i])
        obj[arr[i]] = 1
    } else {
        obj[arr[i]]++
    }
}
return res

}

shenanheng commented 5 years ago
// 第一种方式
  var arr = [1, 2, 2, 4, 1, 5, 8, 10];
  var newArray = [...new Set(arr)];
  // 第二种
  var arr = [1, 2, 2, 4, 1, 5, 8, 10];
  var newArray = [];
  for (let i = 0; i < arr.length; i++) {
    let one = arr[i];
    if(newArray.indexOf(one)<0){
      newArray.push(one);
    }
  }
clark-maybe commented 5 years ago

数组去重我了解到两种方法

set方法(简单粗暴)

function removeItem(list) {
    if(!list){
        return [];
    }else{
        let set = new Set(list);
        return Array.from(set);
    }
}

console.log(removeItem([1,1,1,1,3,4,2]));//[ 1, 3, 4, 2 ]

第二种,推入新数组并判断key是否存在

function removeItem(list) {
    if(!list){
        return [];
    }else{
        let returnList = [];
        for(let i = 0; i<list.length; i++){
            if(returnList.indexOf(list[i]) < 0){
                returnList.push(list[i]);
            }
        }
        return returnList;
    }
}

console.log(removeItem([1,1,1,1,3,4,2]));//[ 1, 3, 4, 2 ]

应该还有很多,暂时想到这些,先工作了,一会看大佬操作.

Yuko7245 commented 5 years ago

1: 最简单数组去重法

function uniq(array){
    var temp = []; //一个新的临时数组
    for(var i = 0; i < array.length; i++){
        if(temp.indexOf(array[i]) == -1){
            temp.push(array[i]);
        }
    }
    return temp;
}

2: set 对象

function uniq(array){
    return […new Set(array)];
}

3: 先排序后相邻去除法

function uniq(array){
    array.sort();
    var temp=[array[0]];
    for(var i = 1; i < array.length; i++){
        if( array[i] !== temp[temp.length-1]){
            temp.push(array[i]);
        }
    }
    return temp;
}

4: 数组下标法

function uniq(array){
    var temp = [];
    for(var i = 0; i < array.length; i++) {
        //如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
        if(array.indexOf(array[i]) == i){
            temp.push(array[i])
        }
    }
    return temp;
}

5: 利用对象属性存在的特性,如果没有该属性则存入新数组。

function uniq(arr) {
            var obj={}
            var newArr=[]
            for (let i = 0; i < arr.length; i++) {
                if (!obj[arr[i]]) {
                    obj[arr[i]] = 1
                    newArr.push(arr[i])
                }   
            }
            return newArr
        }

6: 利用数组原型对象上的includes方法

function uniq(arr) {
            var newArr = []
            for (var i = 0; i < arr.length; i++) {
                if (!newArr.includes(arr[i])) {
                    newArr.push(arr[i])
                }
            }
            return newArr
        }

7: 利用数组原型对象上的 filter 和 includes方法

function uniq(arr) {
            var newArr = []
            newArr = arr.filter(function (item) {
                return newArr.includes(item) ? '' : newArr.push(item)
            })
            return newArr
        }

8: 利用数组原型对象上的 forEach 和 includes方法。

function uniq(arr) {
            var newArr = []
            array.forEach(item => {
                return newArr.includes(item) ? '' : newArr.push(item)
            });
            return newArr
        }
Liruimin2 commented 5 years ago

1.根据索引去重 function uniqcArr(arr){ var tep=[]; for(var i=0;i<arr.length;i++){ if(tem.indexof(arr[i])==-1){ tep.push(arr[i]) } } retuen tep; } 2.es6方法 function uniqcArr(array){ return […new Set(array)]; } 3.利用对象的属性 function uniqueArr(arr){ var hasmap={}; var unique=[]; for(var i=0;i<arr.length;i++){ if(!hasmap.hasOwnproperty([arr[i]])){ unique.push(arraay[i])}} return unique;}

riluocanyang commented 5 years ago

实现一个数组去重的方法

方法一: new Set

function uniqueArr(array) {
  return [...new Set(array)]
}
let arr = [1,2,2,3,3,4,5,6]
uniqueArr(arr)

方法二: 普通方法

function uniqueArr(array) {
  let temp = [];
  for(let i = 0, len = array.length; i < len; i++) {
    if(temp.indexOf(array[i]) === -1) {
      temp.push(arr[i])
    }
  }
  return temp;
}
let arr = [1,2,2,3,3,4,5,6]
uniqueArr(arr)
jodiezhang commented 5 years ago

测试模板 造一个10W数组,造一个5W数组,合并为一个15W数组进行测试

let array1 = Array.from(new Array(100000),(x,index) => {
       return index
})

let array2 = Array.from(new Array(50000),(x,index) =>{
    return index+index
})

let start = new Date().getTime()
console.log('begin to remove duplicates')

function distinct(a, b) {
   //logic to remove duplicates
}

console.log('length after removing duplicate-', distinct(array1,array2).length)

let end = new Date().getTime()
console.log('time spent -',end-start)

第一种方法,效率最低,双循环

function distinct(a, b) {
    let arr = a.concat(b);
    for (let i=0, len=arr.length; i<len; i++) {
        for (let j=i+1; j<len; j++) {
            if (arr[i] == arr[j]) {
                arr.splice(j, 1);
                // splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
                len--;
                j--;
            }
        }
    }
    return arr
}

第二种方法

function distinct(a,b){
   let arr=a.concat(b)
   let result=[]
   for (let i of arr) {
     !result.includes(i) && result.push(i)
}
return result

}

第三种

function distinct(a,b) {
      let arr = a.concat(b)
      arr = arr.sort()
      let result = [arr[0]]
      for (let i=1,len=arr.length;i<len;i++){
      arr[i]!==arr[i-1] && result.push(arr[i])
}
return result;
}

第四种

function distinct(a,b){
   return Array.from(new Set([...a,...b]))
}

第五种 利用对象属性不会重复这一特性

function distinct (a,b){
   let arr=a.concat(b)
   let result=[]
   let obj={}
   for (let i of arr) {
     if(!obj[i]){
        result.push(i)
        obj[i]=1
}
}
return result
}

转载自: https://www.cnblogs.com/wisewrong/p/9642264.html

woyiweita commented 5 years ago

方法一: 使用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", " ", ""]
ZadaWu commented 5 years ago
  1. 使用set来去重
var set1 = new Set([1,1,1,2,2,3,4])
  1. 使用object的key来去重
var a = [1,1,1,2,2,3,4]

function uniqByKey(arr){
    let obj = {}
    arr.forEach(item=>obj[item] = item)
    return Object.values(obj)
}

console.log(uniqByKey(a))
  1. 遍历判断
var a = [1,1,1,2,2,3,4]

function uniqByTraversing(arr){
    let result = []
    arr.forEach(item => {
        if(result.indexOf(item) <= 0) {
            result.push(item)
        } 
    })
    return result
}
console.log(uniqByKey(a))
yangyiqiqia commented 5 years ago

1、使用Set()方法 function myArray(array){ return new Set(array) }; var arrnum = [1,1,2,6,7,3,3,6,4,7]; myArray(arrnum); 2、普通方法去重 function myArray(arr){ var newArray = []; for(var i = 0;i <arr.length;i++){ if(newArray.indexOf(arr[i]) == -1){ newArray.push(arr[i]); } } return newArray; } var array = [1,1,2,3,5,6,4,3,2]; myArray(array); image

chongyangwang commented 5 years ago

1.使用set()方法

var arrList = [1,2,3,4,5,6,1,2]
function setArr(arr){
  return new Set(arr)
}
console.log(setArr(arrList))
  1. 使用indexOf()
var arrlist =[1,2,3,4,5,6,1,2]
function removeSameNum(arr){
   var newArr = []
   for(var i=0;i<arr.length;i++){
     if(newArr.indexOf(arr[i])===-1){
       newArr.push(arr[i])
     }
   }
  return newArr
}
console.log(removeSameNum(arrList))

遍历对象去重(参照上面大佬)

思路 声明空对象 遍历数组 利用Object.keys(赋值) 重复的会覆盖 最后object.values() 取得数组值

var list = [1,2,3,4,5,6];
function uniqueKey(arr){
   let obj={}
   arr.foreach(item=>obj[item] = item)
  return Object.values(obj)
}
console.log(uniqueKey(list))
yelin1994 commented 5 years ago

数组去重

zyq503454535 commented 5 years ago

// 方法一 function unique1(arr) { return [...new Set(arr)] }

// 方法二 function unique2(arr) { var arr1 = [] for(var i = 0; i < arr.length; i++){ if(arr1.indexOf(arr[i]) == -1){ arr1.push(arr[i]) } } return arr1 }

// 方法三 function unique3(arr) { var arr1 = [] for(var i = 0; i < arr.length; i++){ if(!arr1.includes(arr[i])){ arr1.push(arr[i]) } } return arr1 }

// 方法四

function unique4(arr) { var arr1 = [] arr.sort(function(a,b){ return a-b })

for(var i = 0; i < arr.length; i++){ if(arr[i] !== arr[i+1]){ arr1.push(arr[i]) } }

return arr1 }

daibin0809 commented 5 years ago

1.es6 的 set

Array.from(new Set(arr))

2.利用 includes

arr = [1,2,3,4,4,3,2,1]
let result = [];
for(const item of arr){
  if(!result.includes(item)){
    result.push(item);
  }
}
  1. 利用 indexOfsort
    arr.sort((a,b)=>a-b);
    let result =[];
    for(const item of arr){
    if(result.indexOf(item)===-1){
        result.push(item);
    }
    }
mdchun commented 5 years ago

new Set

var arr = [1,2,3,4,4,5,6,3,3,1]
[...new Set(arr)] // [1, 2, 3, 4, 5, 6]

Array.filter


var arr = [1,2,3,4,4,5,6,3,3,1]
var newArr = arr.filter( (item, index, arr) => {
    return index === arr.indexOf(item)
}) // [1, 2, 3, 4, 5, 6]

Object.keys

根据对象的key不重复的特性来实现

var arr = [1,2,3,4,4,5,6,3,3,1]
var o = {}
arr.forEach(e => o[e] = 1) // 随意赋值一个
var newArr = Object.keys(o).map(Number) // [1, 2, 3, 4, 5, 6]

循环过滤存储

var arr = [1,2,3,4,4,5,6,3,3,1]
var s = [];
//遍历数组
for(var i = 0;i<arr.length;i++){
    if(s.indexOf(arr[i]) == -1){  //判断在s数组中是否存在,不存在则push到s数组中
        s.push(arr[i]);
    }
}
console.log(s) // [1, 2, 3, 4, 5, 6]
ParseDark commented 5 years ago

数组去重

大方向啊,先考虑非嵌套数组去重。

然后拓展题, 尝试一下先写测试的函数:

const test = (fn, arg, result) => {
   // 绝对是一个新的思路呢
}

// 解:

// em....我们可以使用, ES6的set
const unit1 = arr => {
    return new Set(arr); 
}

unit1([1, 2, 3, 1]); 

//em....reduce.
const unit2 = arr => {
    return arr.reduce((result, item) => {
        result.includes(item) ? result : result.push(item);
        return result;
    }, [])
}

unit2([1, 2, 3, 1, NaN, NaN, -0, 0, +0, null, null]);

// em....map, 感觉和reduce一样一样的, 不写了。
// em....for.
const unit3 = arr => {
    const result = []
    arr.map(item => {
        result.includes(item) ? void 0: result.push(item);
    }); 
    return result;
}

unit3([1, 2, 3, 1, NaN, NaN, -0, 0, +0, null, null]);

// em...对象的key值不能重复可以利用一下.
const unit4 = arr => {
    let result = [];
    let obj = {};
    arr.map(item => {
        obj[item] = null;
    })
    for(i in obj) {
        result.push(i)
    }

    return result;
}
unit4([1, 2, 3, 1, NaN, NaN, -0, 0, +0, null, null]);

往深的看,嵌套数组去重.往深了走.

  1. 包含数组

  2. 包含对象

那么子问题是, 如何判断一个对象是不是相同.

数组其实就递归使用上面的方法就好呀.

但是再往深的看,其实这里如果自己写判断相等的函数还是涉及到一些坑, 比如类型。js的类型判断有几个坑, 比如-0, NaN, 所以我墙裂推荐大家使用数组的includes方法,它本身的实现已经考虑到js变态的类型机制了。当然你完全可以自己写判断两个元素是否相等的函数, 这绝对没问题.

额, 看来大家的答案, 有实现很酷的算法。好羡慕大佬啊, 算法还有算法导论都是好书,垫桌子真的很棒...

ivan0525 commented 5 years ago

数组下标法

遍历需要去重的数组,如果当前数组的某个元素是第一次出现,则存入新的数组,否则忽略掉。

let unique = function (arr) {
  let temp = []
  arr.forEach((item, index) => {
    if (temp.indexOf(item) === -1) {
      temp.push(item)
    }
  })
  return temp
}

ES6中的Set

let unique = function (arr) {
  return [...new Set(arr)]
}

根据对象的键的不重复性

let unique = function (arr) {
  let obj = {}
  arr.forEach(item => obj[item] = item)
  return Object.keys(obj) // 这里会导致类型被转换(原本是number型的,转成了string类型)
}

ES6中的Map和Set联合使用

let unique = function (arr) {
  const map = new Map()
  return arr.filter(item => !map.has(item) && map.set(item, 1))
}
YvetteLau commented 5 years ago

法1: 利用ES6新增数据类型 Set

Set类似于数组,但是成员的值都是唯一的,没有重复的值。

function uniq(arry) {
    return [...new Set(arry)];
}

法2: 利用 indexOf

function uniq(arry) {
    var result = [];
    for (var i = 0; i < arry.length; i++) {
        if (result.indexOf(arry[i]) === -1) {
            //如 result 中没有 arry[i],则添加到数组中
            result.push(arry[i])
        }
    }
    return result;
}

法3: 利用 includes

function uniq(arry) {
    var result = [];
    for (var i = 0; i < arry.length; i++) {
        if (!result.includes(arry[i])) {
            //如 result 中没有 arry[i],则添加到数组中
            result.push(arry[i])
        }
    }
    return result;
}

法4:利用 reduce

function uniq(arry) {
    return arry.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);
}

法5:利用 Map

function uniq(arry) {
    let map = new Map();
    let result = new Array();
    for (let i = 0; i < arry.length; i++) {
        if (map.has(arry[i])) {
            map.set(arry[i], true);
        } else {
            map.set(arry[i], false);
            result.push(arry[i]);
        }
    }
    return result;
}
KRISACHAN commented 5 years ago
    const Arr = [1,2,3,4,5,5,5,8,7,4,1,2,3,6,10,10,10,'10','10'];
    const uniqueArr = Arr.sort((a,b) => a - b ).filter((e,i,a) => a[i] !== a[i - 1]);
    console.log(uniqueArr );
    const Arr = [1,2,3,4,5,5,5,8,7,4,1,2,3,6,10,10,10,'10','10'];
    const uniqueArr = Array.from(new Set(Arr));
    console.log(uniqueArr );
sinaine commented 5 years ago
  1. set去重
    var arr = [1,1,1,2,1,2,1,'1','2']
    arr = [...new Set(arr)]
  2. Array的原型方法
    const arr =  [1,1,1,2,1,2,1,'1','2']
    let removerepeat = function(nums) {
        nums = nums.filter((val, index) => {
          return index == nums.indexOf(val);
        });
        return nums;
      };
    removerepeat (arr)

    3.map去重

    let remove2 = function(nums) {
      let map = new Map();
      nums.forEach(item => {
        map.set(item, "");
      });
      return map.keys();
    };
    remove2([1, 61, 161, 7, 7, 7, 1, 3, "2", "2"]);
AILINGANGEL commented 5 years ago

1.利用set

function removeDuplicates(arr) {
    return Array.from(new Set(arr));
}

空间复杂度: O(n) 时间复杂度: O(n)

2.排序

function removeDuplicates(arr) {
    arr.sort(function(a, b) {
        return a - b;
    });
    let i = 0;
    let j = 1;
    while (j < arr.length) {
        if (arr[j] !== arr[i]) {
            i++;
            arr[i] = arr[j];
        }
        j++;
    }
    arr.splice(i + 1);
    return arr;
}

时间复杂度: O(nlogn) 空间复杂度: O(1)

lovelycarrot commented 5 years ago

方式一 Set去重

function unique (arr) {
     //return [...new Set(arr)];
     return Array.from(new Set(arr));
}

方式二 indexOf

function unique (arr) {
  const temp = [];
  for (let i = 0; i < arr.length; i++) {
    if (temp.indexOf(arr[i]) == -1) {
      temp.push(arr[i]);
    }
  }
  return temp;
}

方式三 先排序在去重

function unique (array) {
  array.sort();
  const temp = [];
  for (let i = 0; i < array.length; i++) {
    if (array[i] !== array[i + 1]) {
      temp.push(array[i]);
    }
  }
  return temp;
}

方式四 利用filter和includes

function unique (arr) {
  let temp = [];
  temp = arr.filter(element => {
    return temp.includes(element) ? '' : temp.push(element);
  });
  return temp;
}

方式五 利用对象属性方法

function unique (array) {
  let object = {};
  let temp = [];
  array.forEach(element => {
    if (!object[element]) {
      object[element] = 1;
      temp.push(element);
    }
  });
  return temp;
}
MissNanLan commented 5 years ago

简单的数组去重

// 利用Set对象
  let arr = [1,2,3,4,5,5,6,null,null,undefined];
console.log(...new Set(arr));

// 利用Map对象
function unique(arr) {
  const arrMap = new Map();
   return arr.filter(item=> !arrMap.has(item) && arrMap.set(item,1))
}
 let arr = [1,2,3,4,5,5,6,null,null,undefined];
 console.log(unique(arr));

// 利用indexof
function unique(arr) {
 let uniqueArr = [];
  arr.forEach((item,index) =>{
    if(uniqueArr.indexOf(item) === -1){
      uniqueArr.push(item);
    }
  })
  return  uniqueArr;
}
 let arr = [1,2,3,4,5,5,6,null,null,undefined];
 console.log(unique(arr));

 // 利用reduce(这种写法还是第一次见,长见识了)
function unique(arry) {
    return arry.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);
}
 let arr = [1,2,3,4,5,5,6,null,null,undefined];
 console.log(unique(arr));

数组对象去重

function unique(arr, key) {
    const map = new Map()
    return arr.filter((item) => !map.has(item[key] + '') && map.set(item[key] + '', 1))
}
let arr = [
    { name: 'a', num: 1},
    { name: 'b', num: 1},
    { name: 'c', num: 1},
    { name: 'd', num: 1},
    { name: 'a', num: 1},
    { name: 'a', num: 1},
    { name: 'a', num: 1}
]
 console.log(unique(arr));
lydfree commented 5 years ago

1.new Set(简单粗暴)

function DeWeighting(array){ return [...new Set(array)] }

2.indexOf

function DeWeighting(array){ let temp = [] array.forEach(element => { if(temp.indexOf(element) == -1){ temp.push(element) } }); return temp }

3.includes

function DeWeighting(array){ let temp = [] array.forEach(element => { if(!temp.includes(element)){ temp.push(element) } }); return temp }