javascript 数组 重复-关于JavaScript字段去重的一些理解总结

前言

自己做了几年后端开发,在项目中使用链表去重的机会并不多,笔试的时候也经常被问到。 就我个人而言,我理解这个问题确实测试了 JavaScript 的基础知识。 因为有很多方法可以做到这一点。 这次根据这道题,把相关的知识都搞明白了。

1.ES6中的NewSet形式

首先看MDN上Set的描述:

设置对象允许您存储任何类型的唯一值,无论是原始值还是对象引用。

Set 对象是值的集合javascript 数组 重复,您可以按照插入顺序对其元素进行迭代。 Set中的元素只会出现一次javascript 数组 重复,即Set中的元素是唯一的。

关键字:可以存储任何类型,并且存储的值是唯一的,这样可以先去除链表中的重复数据。

const list1 = [1, 2, 3, 7, 11, 56, 3, 2, 4, 5]
const list2 = new Set(list1)
console.log(list2) 

看一下返回的结果:

从结果可以看出,返回的是一个可迭代的Set对象,此时需要将Set对象转换为链表。此时可用

大批。 从()。

**Array.from()** 方法从类似链表或可迭代的对象创建一个新的浅复制链表实例。

碰巧 newSet() 返回一个可迭代对象。

const list3 = Array.from(new Set([null, null, undefined, 12, undefined, 7, 2, 1, 22, 2, function a(){}, function a(){}, {}, {}]))

结果是返回一个链表:

这些方法不考虑兼容性,无法去除重复的函数和{}

Array.from() 的扩展

Array.from(arrayLike[,mapFn[,thisArg]])

arrayLike:伪链表和可迭代对象

mapFn:每个元素都会执行这个bounce方法

thisArg:执行bounce函数时的this点。

const list4 = Array.from("name", arg => arg + 12)
console.log(list4) // [ "n12", "a12", "m12", "e12" ]

伪链表对象(任何具有长度属性和多个索引属性的对象,例如字符串)

可迭代对象(可以获取对象中的元素,如Map和Set等)

2.集合的另一种写法

const list20 = [5, 3, 5, 5, 6, 37, 22, 22]
console.log([...new Set(list20)])

虽然和第一部类似

3. 嵌套for循环

const list5 = [null, null, undefined, undefined, {}, {}, function q() {}, function q() {}, 34, 2, 1, 2]
for(let i = 0; i < list3.length; i++) {
  for (let j = i + 1; j < list3.length; j++) {
    if (list3[i] === list3[j]) {
      list3.splice(j, 1) // 将重复的数据删掉一个
      j-- // 因为删除掉了一个元素,就从这个元素的索引重新开始
    }
  }
}

这些方法使用了 splice(index, num) 的方法,返回的结果并没有移除函数和对象。 我们能想到的最简单的方法就是这些形式的重复数据删除。

四、indexOf形式

const list6 = [null, null, undefined, undefined, NaN, NaN, false, "false", function a(){}, function a() {}, {}, {}]
const list7 = []
for(let k = 0; k<list6.length; k++) {
  if (list7.indexOf(list6[k]) === -1) {
    list7.push(list6[k])
  }
}
console.log(list7, "list7") 
// [null, undefined,NaN, NaN,false,"false",[Function: a], [Function: a],{},{}] list7

关于indexOf

这个技巧在数组构造函数和字符串构造函数的原型上都可用

MDN 上对它们的解释是:

**indexOf()** 方法返回在链表中可以找到给定元素的第一个索引,如果不存在则返回 -1。

arr.indexOf(searchElement[, fromIndex])

**indexOf()** 方法返回调用它的 String 对象中指定值第一次出现的索引,并从 fromIndex 开始搜索。 如果未找到该值,则返回 -1。

str.indexOf(searchValue [, fromIndex])

从这一点就可以看出两者的用法是一样的。

五、排序

我们看一下关于sort的解释:

**sort()** 方法使用就地算法对链表的元素进行排序并返回字段。默认排序顺序是在将元素转换为字符串然后比较它们的 UTF-16 代码单元序列时建立的价值观

因为要看具体的实现,所以很难保证排序的时间复杂度和空间复杂度。

因此,当链表很长时,这些方法可能无法保证性能。 用它来减肥有哪些想法? 首先使用sort进行排序,然后比较前一个和后一个,这样相同的值始终是相邻关系。

const list8 = [null, null, undefined, undefined, NaN, NaN, false, "false", function a(){}, function a() {}, {}, {}]
const list9 = list8.sort()
const list10 = [list9[0]]
for(let i = 1; i<list9.length; i++) {
  if (list9[i] !== list9[i-1]) {
    list10.push(list9[i])
  }
}

这很容易理解。

六、包括

const list11 = [null, null, undefined, undefined, NaN, NaN, false, "false", function a(){}, function a() {}, {}, {}]
const list12 = []
for (let i = 0; i<list11.length ; i++) {
  if (!list12.includes(list11[i])) {
    list12.push(list11[i])
  }
}

在此结果中,函数和 {} 未进行重复数据删除,其他所有内容均已进行重复数据删除。

include 也是 Array 构造函数和 String 构造函数上的方法。

七、filter和indexOf

// 数组去重方式6-filter和indexOf
const list13 = [1, 2, 3, 3, 5]
const list14 = list13.filter((item, index, arr) => {
  // 也就是在遍历这个数组list13的时候,每次拿当前的元素跟此数组中这个元素第一次出现的位置相比,如果位置是一致的,就返回当前元素
  return list13.indexOf(item, 0) === index
})

8. 递归

const list15 = [1, 2, 3, 4, 5, 7, 6, 4, 3]
const list16 = list15
const len = list16.length
list16.sort(function(a, b) { return a - b }) // 先排序
function loop(index) {
  if (index >= 1) {
    if (list16[index] === list16[index - 1]) {
      list16.splice(index, 1)
    }
  loop(index - 1)
  }
}
loop(len - 1)

关于排序

我们在排序的时候可能会忽略一个问题,可能得不到我们想要的结果,比如下面的例子:

const list17 = [22, 1, 2, 15, 3, 4, 3, 1, 11]
console.log(list17.sort()) // [1, 1, 11, 15, 2, 22, 3, 3, 4]

看看得到的结果,根本就不是按照从小到大的排名。 这是因为默认排序顺序是在将元素转换为字符串然后比较它们的 UTF-16 代码单元值序列时建立的。

所以要找到另一种排序方式就是传递一个函数来排序。

编曲排序([比较函数])

范围:

返回值:

返回的是一个已经排序好的链表。

9.利用Map数据结构排序

const list 18 = [2, 3, 33, 2, 5, 1, 3]
const map1 = new Map()
for(let i = 0; i<list18.length; i++) {
  if (map1.get(list18[i])) {
    map1.set(list18[i], true)
  } else {
    map1.set(list18[i], false)
    list19.push(list18[i])
  }
}

这个比较容易理解,就不多说了。

总结

关于JavaScript链表去重的一些理解这篇文章就到此结束了。 更多相关JavaScript链表去重内容,请搜索云海天教程往期文章或继续浏览下方相关文章。 希望大家以后多多支持云海。 日教程!

原文链接: