Hay más de una docena de soluciones para la deduplicación de matriz js, ¿el conocimiento básico es sólido? (con el método de matriz)

prefacio

Vi el lema de un excavador, Hablar es barato, muéstrame el código . Esta frase es muy interesante.

1. Deduplicación de arreglos de tipos básicos

1. El método más directo y eficiente [operador de propagación + Set()]

En el trabajo real, se recomienda usar directamente este método para eliminar pesos, lo cual es conveniente y asequible. SetUn objeto es una colección de valores y puede iterar sobre sus elementos en el orden en que se insertaron. Los elementos del Conjunto solo aparecen una vez , es decir, los elementos del Conjunto son únicos.

function removeDuplicate_1(arr) {
  return [... new Set(arr)]
}
复制代码

Lo anterior es en realidad equivalente a
let set = new Set(arr); return [... set];
Aquí sethay un objeto de colección, deconstruyendo cada elemento en una matriz por medio de la estructura.

2. Use el método array api reduce [es necesario ordenar primero]

La siguiente condición if se puede escribir así if(prev.indexOf(cur) === -1), es el método indexOf(), si no está en el anterior, simplemente empújelo cerca de result.push, si lo hay, no ingresará en la matriz de resultados,

function removeDuplicate_2(arr) {
  arr.sort((a, b) => a - b) // 数组升序排序
  return  arr.reduce((prev, cur) => { // 这里return最后结果就是prev 的最后结果
  // 第一次数组为空时|| prev 数组的最后一项不等于arr 的下一项的话 ,把当前项cur push到prev数组中,
    if (prev.length === 0 || (prev[prev.length - 1] !== cur)) { 
      prev.push(cur)
    }
    return prev;  // 这里返回的prev 会成为 reduce(prev,cur)这里prev 的新值
  }, [])
}
复制代码

Introducción al método de reducción

De forma general arr.reduce((p,c)=>{ fn content;return p },init), se introducirán y asentarán los siguientes parámetros específicos.

Resumen : El parámetro reduce incluye una función y un valor inicial. El valor inicial es opcional. La función tiene cuatro parámetros opcionales. Cuando hay un valor inicial, anteriorValor = valor inicial (valor inicial), valor actual = el primer elemento de la matriz arr [0], sin valor de valor inicial , p = arr[0], c = arr[1]. El resultado de la devolución se usa como el valor inicial de p para la siguiente iteración.

  • Una función "reductora" con cuatro parámetros:

    • previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]
    • currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]
    • currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。
    • array:用于遍历的数组。
  • initialValue 可选

  • 作为第一次调用 callback 函数时参数 previousValue 的值。若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。

用途

1、求数组所有值的和

let sum = [0, 1, 2, 3].reduce(function (previousValue, currentValue) {
  return previousValue + currentValue
}, 0)
// sum is 6

复制代码

2 、累加对象数组里的值

let initialValue = 0
let sum = [{x: 1}, {x: 2}, {x: 3}].reduce(
    (previousValue, currentValue) => previousValue + currentValue.x
    , initialValue
)

console.log(sum) // logs 6

复制代码

更多实例参考官方文档

看看有无初始值的情况
无初始值时 reduce() 如何运行

假如运行以下无初始值的 reduce() 代码:

const array = [15, 16, 17, 18, 19];

function reducer(previous, current, index, array) {
  const returns = previous + current;
  console.log(`previous: ${previous}, current: ${current}, index: ${index}, returns: ${returns}`);
  return returns;
}

array.reduce(reducer);
复制代码

callback 被调用四次,每次调用的参数和返回值如下表:

callback iteration previousValue currentValue currentIndex array return value
first call 15 16 1 [15, 16, 17, 18, 19] 31
second call 31 17 2 [15, 16, 17, 18, 19] 48
third call 48 18 3 [15, 16, 17, 18, 19] 66
fourth call 66 19 4 [15, 16, 17, 18, 19] 85

由 reduce() 返回的值将是最后一次回调返回值(85)。

有初始值时 reduce() 如何运行

在这里,我们以相同的算法 reduce 同一个数组,但提供 10 作为初始值:

[15, 16, 17, 18, 19].reduce( (previousValue, currentValue, currentIndex, array) => previousValue + currentValue, 10 )
复制代码

Copy to Clipboard

callback iteration previousValue currentValue currentIndex array return value
first call 10 15 0 [15, 16, 17, 18, 19] 25
second call 25 16 1 [15, 16, 17, 18, 19] 41
third call 41 17 2 [15, 16, 17, 18, 19] 58
fourth call 58 18 3 [15, 16, 17, 18, 19] 76
fifth call 76 19 4 [15, 16, 17, 18, 19] 95

这种情况下 reduce() 返回的值是 95

3、使用一个for循环解决【需要先排序】

1、声明一个新数组result来存放,去重后的数组 。

2、给数组排序。

3、循环排序后的数组, 若第i项不等于第i-1项,则把此项内容push到result数组, 注意这里和常规的,用当前项于下一项对比的方式不同, arr[i- 1] 这里是arr[-1],结果是undefined的,js 语言的特性,所以可以这样操作吧,思考一下(1),用if(arr[i] !== arr[i + 1])可以吗,评论区说出你的答案,为什么?

4、 返回结果result

function removeDuplicate_3(arr) {
  let result = []
  arr.sort((a, b) => a - b)
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== arr[i - 1]) {
      result.push(arr[i])
    }
  }
  return result
}
复制代码

sort 方法介绍

 arr.sort((a, b) => a - b) // 升序
  arr.sort((a, b) => b - a) // 降序
复制代码

4、使用数组api indexOf() 方法

function removeDuplicate_4(arr) {
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    if (result.indexOf(arr[i]) == -1) {
      result.push(arr[i])
    }
  }
  return result;
}
复制代码

indexOf() 方法介绍

indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
概括:接收两个参数,返回下标值。arr.indexOf(要查找的元素,从那个位置开始查找)

示例

var array = [2, 5, 9];
array.indexOf(2);     // 0
array.indexOf(7);     // -1
array.indexOf(9, 2);  // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

复制代码

indexOf()方法详细介绍

5、使用数组api Array.from() 方法和 Set 对象

function removeDuplicate_5(arr) {
  return Array.from(new Set(arr))
}
复制代码

Array.from()  方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

概括: 接收三个参数,返回数组。Array.from(要处理的类数组对象,fn【回调函数可选】, this【执行回调函数时的this指向,可选】)

注意: 使用的时Array.from ,而不是数组实例arr.from,类似于Java的静态方法用类名调用。

Array.From() 详细介绍

6、使用一个for循环 、利用对象的存储特性

function removeDuplicate_6(arr) {
  let result = [], obj = {};
  for (let item of arr) {
    if (!obj[item]) {
      result.push(item);
      obj[item] = 1
    } else {
      obj[item]++
    }
  }
  return result;
}
复制代码

7、使用数组api filter 和indexOf 方法结合原型的this的call调用

function removeDuplicate_7(arr) {
  return Array.prototype.filter.call(arr, (item, index) => {
    return arr.indexOf(item) === index
  })
}

复制代码

8 、利用数组快慢指针的方式

function removeDuplicate_8(arr) {
  let fast = 0, low = -1, result = [];
  arr.sort((a,b) => a - b)
  while (fast < arr.length) {
    if (arr[fast] !== arr[low]) {
      result.push(arr[fast])
    }
    fast++
    low++
  }
  return result;
}
复制代码

二、数组对象类型的去重

9 、利用数组的filter对象和 Map 对象去重数组里的对象

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。 Map 对象

filter()  方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。


let arr_obj = [
  {
    id: 1,
    name: '张三',
    age: 18,
    sex: 1
  },
  {
    id: 2,
    name: '李四',
    age: 20,
    sex: 2
  },
  {
    id: 1,
    name: '张三',
    age: 18,
    sex: 1
  },
  {
    id: 3,
    name: '王老五',
    age: 18,
    sex: 2
  },
  {
    id: 4,
    name: '王老五',
    age: 18,
    sex: 2
  }
]
function removeDuplicate_10(arr, attr) {
  const result = new Map();
  return arr.filter((item) => !result.has(item[attr]) && result.set(item[attr], 1))
}

console.log(arr_obj);
console.log(removeDuplicate_10(arr_obj, 'name')); // 以对象姓名去重
复制代码

上面filter()里面的内容会不好理解吗它相当于


function removeDuplicate_11(arr, attr) {
  const result = new Map();
  let fn = (item) => {
    if(!result.has(item[attr])) {
     return result.set(item[attr], 1)
    }
  }
  return arr.filter(fn)
}
复制代码

!result.has(item[attr]) && result.set(item[attr], 1)) 相当于

 if(!result.has(item[attr])) {
     result.set(item[attr], 1)
 }
 //由于箭头函数没有带{}花括号,所以是有return的, 所以会相当于这样
  if(!result.has(item[attr])) {
     return result.set(item[attr], 1)
    }
复制代码

去重前

[
  { id: 1, name: '张三', age: 18, sex: 1 },
  { id: 2, name: '李四', age: 20, sex: 2 },
  { id: 1, name: '张三', age: 18, sex: 1 },
  { id: 3, name: '王老五', age: 18, sex: 2 },
  { id: 4, name: '王老五', age: 18, sex: 2 }
]
复制代码

去重后

[
  { id: 1, name: '张三', age: 18, sex: 1 },
  { id: 2, name: '李四', age: 20, sex: 2 },
  { id: 3, name: '王老五', age: 18, sex: 2 }
]
复制代码

以id 去重

console.log(removeDuplicate_8(arr_obj, 'id'));
[
  { id: 1, name: '张三', age: 18, sex: 1 },
  { id: 2, name: '李四', age: 20, sex: 2 },
  { id: 3, name: '王老五', age: 18, sex: 2 },
  { id: 4, name: '王老五', age: 18, sex: 2 }
]

复制代码

10 、使用数组方法reduce和对象特性

思路是创建一个空对象,判断对象里有没有该属性的值,没有就吧该项push 到数组存储

function removeDuplicate_12(arr, attr) {
  let obj = {}
  return arr.reduce((prev,curr) =>{
    // 这种三元运算符的方式是不是不好理解,看看下面10的做法,转化为if判断就好理解了。
    obj[curr[attr]] ? '' : obj[curr[attr]] = true && prev.push(curr) // ''为空的意思
     // 写法上也可以 为undefined 
    // obj[curr[attr]] ? undefined : obj[curr[attr]] = true && prev.push(curr)
    return prev
  },[])
}
console.log(removeDuplicate_12(arr_obj, 'name'));
复制代码

11、使用for of 循环加对象特性。

思路和9的类似,知识迭代方式不同。

function removeDuplicate_13(arr, attr) {
  let obj = {}, result = [];
  for(let item of arr){
    if(!obj[item[attr]]) {
      result.push(item)
      obj[item[attr]] =  true
    }
  }
  return result;
}
console.log(removeDuplicate_13(arr_obj, 'id'));
复制代码

相关文章参考

JS对象数组去重的三种方法

数组去重

Supongo que te gusta

Origin juejin.im/post/7081572865220280333
Recomendado
Clasificación